Fixes and updates

This commit is contained in:
Nico committed 2021-03-07 15:22:55 +01:00
1 parent d1710ea6a5
commit fb4da77359
211 files changed
+45363 -45571

No files matched your search

@@ -18,6 +18,7 @@ import javax.swing.KeyStroke;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.LdcInsnNode; import org.objectweb.asm.tree.LdcInsnNode;
@@ -141,6 +142,7 @@ public class GlobalSearchBox extends JFrame {
if (ignoreCase) { if (ignoreCase) {
str = str.toLowerCase(); str = str.toLowerCase();
} }
String fstr = str;
for (ClassNode cn : Main.classNodes.values()) { for (ClassNode cn : Main.classNodes.values()) {
for (MethodNode mn : cn.methods) { for (MethodNode mn : cn.methods) {
for (AbstractInsnNode insn : mn.instructions.toArray()) { for (AbstractInsnNode insn : mn.instructions.toArray()) {
@@ -154,6 +156,15 @@ public class GlobalSearchBox extends JFrame {
} }
} }
} }
if (mn.visibleAnnotations != null) {
for (AnnotationNode anno : mn.visibleAnnotations) {
if (anno.values == null)
continue;
anno.values.stream().filter(o -> o instanceof String).map(o -> (String) o)
.map(s -> ignoreCase ? s.toLowerCase() : s).filter(s -> s.contains(fstr))
.forEach(s -> set.add(new Info(cn.name, mn.name, mn.desc, mn)));
}
}
} }
} }
} else { } else {
+8 -123
View File
@@ -106,7 +106,7 @@ public class Disassembler {
AtomicInteger lineFound = new AtomicInteger(-1); AtomicInteger lineFound = new AtomicInteger(-1);
StringContext ctx = new StringContext(18); StringContext ctx = new StringContext(18);
ctx.next("// #Annotations:\n"); ctx.next("// #Annotations:\n");
ctx.next(doAnnotations(classNode.visibleAnnotations, hs)); ctx.next(doAnnotations(classNode.visibleAnnotations, hs, ""));
ctx.next("// #Class v:" + classNode.version + "\n"); ctx.next("// #Class v:" + classNode.version + "\n");
if (classNode.signature != null) if (classNode.signature != null)
ctx.next("// #Signature: " + UnicodeUtils.escapeWithSpaces(hs, classNode.signature) + "\n"); ctx.next("// #Signature: " + UnicodeUtils.escapeWithSpaces(hs, classNode.signature) + "\n");
@@ -165,12 +165,12 @@ public class Disassembler {
} }
} }
private static String doAnnotations(List<AnnotationNode> annotations, HugeStrings hs) { private static String doAnnotations(List<AnnotationNode> annotations, HugeStrings hs, String linePrefix) {
if (annotations == null) if (annotations == null)
return ""; return "";
StringContext ctx = new StringContext(annotations.size()); StringContext ctx = new StringContext(annotations.size());
for (AnnotationNode annotationNode : annotations) { for (AnnotationNode annotationNode : annotations) {
String s = "@" + UnicodeUtils.escapeWithSpaces(hs, annotationNode.desc); String s = linePrefix + "@" + UnicodeUtils.escapeWithSpaces(hs, annotationNode.desc);
if (annotationNode.values != null && !annotationNode.values.isEmpty()) { if (annotationNode.values != null && !annotationNode.values.isEmpty()) {
s += " ("; s += " (";
boolean valBefore = true; boolean valBefore = true;
@@ -213,7 +213,7 @@ public class Disassembler {
s += ", "; s += ", ";
} }
s = s.substring(0, s.length() - 2); s = s.substring(0, s.length() - 2);
s += " }]"; s += " }], ";
} else if (o instanceof String) { } else if (o instanceof String) {
s += "\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"], "; s += "\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"], ";
} else { } else {
@@ -249,66 +249,8 @@ public class Disassembler {
String[] dis = disassembleMethod(className, mn, hs); String[] dis = disassembleMethod(className, mn, hs);
ms += dis[2]; ms += dis[2];
ms += dis[1]; ms += dis[1];
if (mn.visibleAnnotations != null && !mn.visibleAnnotations.isEmpty()) { if (mn.visibleAnnotations != null && !mn.visibleAnnotations.isEmpty())
for (AnnotationNode annotationNode : mn.visibleAnnotations) { ms += doAnnotations(mn.visibleAnnotations, hs, "\t");
ms += "\t@" + annotationNode.desc;
if (annotationNode.values != null && !annotationNode.values.isEmpty()) {
ms += " (";
boolean valBefore = true;
for (Object o : annotationNode.values) {
if (valBefore) {
ms += o + " = [";
valBefore = false;
continue;
} else {
if (o instanceof String[]) {
String[] arr = (String[]) o;
boolean w8ing = false;
for (String rofl : arr) {
if (!w8ing) {
ms += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
w8ing = true;
} else {
ms += UnicodeUtils.escapeWithSpaces(hs, rofl) + "]";
}
}
ms += ", ";
} else if (o instanceof List) {
List list = (List) o;
ms += "{ ";
for (Object obj : list) {
if (obj instanceof String[]) {
String[] arr = (String[]) obj;
boolean w8ing = false;
for (String rofl : arr) {
if (!w8ing) {
ms += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
w8ing = true;
} else {
ms += UnicodeUtils.escapeWithSpaces(hs, rofl);
}
}
} else {
ms += "\"" + UnicodeUtils.escape(hs, String.valueOf(obj))
+ "\"";
}
ms += ", ";
}
ms = ms.substring(0, ms.length() - 2);
ms += " }]";
} else {
ms += "(" + o.getClass().getName().replace(".", "/") + ") " + o + "], ";
}
valBefore = true;
}
}
if (ms.endsWith(", "))
ms = ms.substring(0, ms.length() - 2);
ms += ")";
}
ms += "\n";
}
}
if (mn.equals(nodeToFind)) { if (mn.equals(nodeToFind)) {
lineFound.set(ms.split("\\n").length); lineFound.set(ms.split("\\n").length);
} }
@@ -359,65 +301,8 @@ public class Disassembler {
String s = ""; String s = "";
if (fn.signature != null) if (fn.signature != null)
s += "\t// #Signature: " + UnicodeUtils.escapeWithSpaces(hs, fn.signature) + "\n"; s += "\t// #Signature: " + UnicodeUtils.escapeWithSpaces(hs, fn.signature) + "\n";
if (fn.visibleAnnotations != null && !fn.visibleAnnotations.isEmpty()) { if (fn.visibleAnnotations != null && !fn.visibleAnnotations.isEmpty())
for (AnnotationNode annotationNode : fn.visibleAnnotations) { s += doAnnotations(fn.visibleAnnotations, hs, "\t");
s += "\t@" + UnicodeUtils.escapeWithSpaces(hs, annotationNode.desc);
if (annotationNode.values != null && !annotationNode.values.isEmpty()) {
s += " (";
boolean valBefore = true;
for (Object o : annotationNode.values) {
if (valBefore) {
s += o + " = [";
valBefore = false;
continue;
} else {
if (o instanceof String[]) {
String[] arr = (String[]) o;
boolean w8ing = false;
for (String rofl : arr) {
if (!w8ing) {
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
w8ing = true;
} else {
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "]";
}
}
s += ", ";
} else if (o instanceof List) {
List list = (List) o;
s += "{ ";
for (Object obj : list) {
if (obj instanceof String[]) {
String[] arr = (String[]) obj;
boolean w8ing = false;
for (String rofl : arr) {
if (!w8ing) {
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
w8ing = true;
} else {
s += UnicodeUtils.escapeWithSpaces(hs, rofl);
}
}
} else {
s += "\"" + UnicodeUtils.escape(hs, String.valueOf(obj)) + "\"";
}
s += ", ";
}
s = s.substring(0, s.length() - 2);
s += " }]";
} else {
s += "(" + o.getClass().getName().replace(".", "/") + ") " + o + "], ";
}
valBefore = true;
}
}
if (s.endsWith(", "))
s = s.substring(0, s.length() - 2);
s += ")";
}
s += "\n";
}
}
if (fn.equals(nodeToFind)) { if (fn.equals(nodeToFind)) {
lineFound.set(s.split("\\n").length); lineFound.set(s.split("\\n").length);
} }
+14 -12
View File
@@ -33,12 +33,12 @@ import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.swing.ButtonGroup; import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem; import javax.swing.JCheckBoxMenuItem;
@@ -311,7 +311,7 @@ public class Main extends JFrame {
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
try { try {
ArchiveTreeModel model = new ArchiveTreeModel(new JarFile(jarFile)); ArchiveTreeModel model = new ArchiveTreeModel(new ZipFile(jarFile));
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(new Runnable() {
public void run() { public void run() {
synchronized (treeLock) { synchronized (treeLock) {
@@ -466,7 +466,7 @@ public class Main extends JFrame {
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
try { try {
ArchiveTreeModel model = new ArchiveTreeModel(new JarFile(jarFile)); ArchiveTreeModel model = new ArchiveTreeModel(new ZipFile(jarFile));
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(new Runnable() {
public void run() { public void run() {
synchronized (treeLock) { synchronized (treeLock) {
@@ -560,7 +560,7 @@ public class Main extends JFrame {
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
try { try {
ArchiveTreeModel model = new ArchiveTreeModel(new JarFile(jarFile)); ArchiveTreeModel model = new ArchiveTreeModel(new ZipFile(jarFile));
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(new Runnable() {
public void run() { public void run() {
synchronized (treeLock) { synchronized (treeLock) {
@@ -786,6 +786,8 @@ public class Main extends JFrame {
public void goToSelected() throws BadLocationException { public void goToSelected() throws BadLocationException {
int lineStart = txtByteEditView.getLineStartOffsetOfCurrentLine(); int lineStart = txtByteEditView.getLineStartOffsetOfCurrentLine();
int lineEnd = txtByteEditView.getLineEndOffsetOfCurrentLine() - 1; int lineEnd = txtByteEditView.getLineEndOffsetOfCurrentLine() - 1;
if (lineEnd < lineStart)
return;
String line = txtByteEditView.getText(lineStart, lineEnd - lineStart); String line = txtByteEditView.getText(lineStart, lineEnd - lineStart);
if (!jumpableInstructionPattern.matcher(line).matches()) { if (!jumpableInstructionPattern.matcher(line).matches()) {
return; return;
@@ -1042,7 +1044,7 @@ public class Main extends JFrame {
public void save(File jar, Collection<ClassNode> classes) { public void save(File jar, Collection<ClassNode> classes) {
try { try {
final JarOutputStream output = new JarOutputStream(new FileOutputStream(jar)); final ZipOutputStream output = new ZipOutputStream(new FileOutputStream(jar));
if (tree.getModel().getClass().equals(DefaultTreeModel.class) if (tree.getModel().getClass().equals(DefaultTreeModel.class)
|| ((ArchiveTreeModel) tree.getModel()).newCreated) { || ((ArchiveTreeModel) tree.getModel()).newCreated) {
int acc = ClassUtil.ACC_PUBLIC | ClassUtil.ACC_STATIC; int acc = ClassUtil.ACC_PUBLIC | ClassUtil.ACC_STATIC;
@@ -1067,7 +1069,7 @@ public class Main extends JFrame {
((ArchiveTreeModel) tree.getModel()).newCreated = false; ((ArchiveTreeModel) tree.getModel()).newCreated = false;
} }
for (Entry<String, byte[]> entry : OTHER_FILES.entrySet()) { for (Entry<String, byte[]> entry : OTHER_FILES.entrySet()) {
JarEntry ent = new JarEntry(entry.getKey()); ZipEntry ent = new ZipEntry(entry.getKey());
output.putNextEntry(ent); output.putNextEntry(ent);
output.write(entry.getValue()); output.write(entry.getValue());
output.closeEntry(); output.closeEntry();
@@ -1082,7 +1084,7 @@ public class Main extends JFrame {
for (ClassNode node : classes) { for (ClassNode node : classes) {
ClassWriter writer = new ClassWriter(computeFlags); ClassWriter writer = new ClassWriter(computeFlags);
node.accept(writer); node.accept(writer);
output.putNextEntry(new JarEntry(getFullName(node.name))); output.putNextEntry(new ZipEntry(getFullName(node.name)));
output.write(writer.toByteArray()); output.write(writer.toByteArray());
output.closeEntry(); output.closeEntry();
} }
@@ -1123,16 +1125,16 @@ public class Main extends JFrame {
newCreated = true; newCreated = true;
} }
public ArchiveTreeModel(JarFile jar) { public ArchiveTreeModel(ZipFile jar) {
super(new ByteEditTreeNode(jar.getName().split(File.separator.equals("\\") ? "\\\\" super(new ByteEditTreeNode(jar.getName().split(File.separator.equals("\\") ? "\\\\"
: File.separator)[jar.getName().split(File.separator.equals("\\") ? "\\\\" : File.separator).length : File.separator)[jar.getName().split(File.separator.equals("\\") ? "\\\\" : File.separator).length
- 1])); - 1]));
try { try {
classNodes.clear(); classNodes.clear();
OTHER_FILES.clear(); OTHER_FILES.clear();
Enumeration<JarEntry> enumeration = jar.entries(); Enumeration<? extends ZipEntry> enumeration = jar.entries();
while (enumeration.hasMoreElements()) { while (enumeration.hasMoreElements()) {
JarEntry next = enumeration.nextElement(); ZipEntry next = enumeration.nextElement();
byte[] data = toByteArray(jar.getInputStream(next)); byte[] data = toByteArray(jar.getInputStream(next));
if (next.getSize() != 0 && !next.getName().startsWith("META-INF") if (next.getSize() != 0 && !next.getName().startsWith("META-INF")
&& (next.getName().endsWith(".class") || next.getName().endsWith(".class/"))) { && (next.getName().endsWith(".class") || next.getName().endsWith(".class/"))) {
+1 -1
View File
@@ -12,7 +12,7 @@
<baseFont size="12"/> <baseFont size="12"/>
<!-- General editor colors. --> <!-- General editor colors. -->
<background color="ffffff"/> <background color="c0c0c0"/>
<caret color="000000"/> <caret color="000000"/>
<selection bg="dddddd" fg="000000"/> <selection bg="dddddd" fg="000000"/>
<currentLineHighlight color="dddddd" fade="false"/> <currentLineHighlight color="dddddd" fade="false"/>
+3 -3
View File
@@ -12,10 +12,10 @@
<baseFont size="12"/> <baseFont size="12"/>
<!-- General editor colors. --> <!-- General editor colors. -->
<background color="000000"/> <background color="2f2f2f"/>
<caret color="eeeeee"/> <caret color="eeeeee"/>
<selection bg="222222" fg="eeeeee"/> <selection bg="111111" fg="eeeeee"/>
<currentLineHighlight color="222222" fade="false"/> <currentLineHighlight color="111111" fade="false"/>
<marginLine fg="4f4b46"/> <marginLine fg="4f4b46"/>
<markAllHighlight color="947e76"/> <!-- TODO: Fix me --> <markAllHighlight color="947e76"/> <!-- TODO: Fix me -->
<markOccurrencesHighlight color="2b2b2b" border="false"/> <markOccurrencesHighlight color="2b2b2b" border="false"/>
+38 -46
View File
@@ -20,7 +20,7 @@ import javax.swing.text.Segment;
* @version 1.0 * @version 1.0
*/ */
public class DocumentReader extends Reader { public class DocumentReader extends Reader {
/** /**
* The stream's position in the document. * The stream's position in the document.
*/ */
@@ -37,12 +37,11 @@ public class DocumentReader extends Reader {
* Used for fast character access. * Used for fast character access.
*/ */
private Segment segment; private Segment segment;
/** /**
* Constructor. * Constructor.
* *
* @param document * @param document The document we're 'reading'.
* The document we're 'reading'.
*/ */
public DocumentReader(Document document) { public DocumentReader(Document document) {
position = 0; position = 0;
@@ -50,34 +49,34 @@ public class DocumentReader extends Reader {
this.document = document; this.document = document;
this.segment = new Segment(); this.segment = new Segment();
} }
/** /**
* This currently does nothing... * This currently does nothing...
*/ */
@Override @Override
public void close() {} public void close() {
}
/** /**
* Marks the present position in the stream. Subsequent calls to * Marks the present position in the stream. Subsequent calls to
* <code>reset()</code> will reposition the stream to this point. * <code>reset()</code> will reposition the stream to this point.
* *
* @param readAheadLimit * @param readAheadLimit Ignored.
* Ignored.
*/ */
@Override @Override
public void mark(int readAheadLimit) { public void mark(int readAheadLimit) {
mark = position; mark = position;
} }
/** /**
* Tells whether this reader supports the <code>mark</code> operation. * Tells whether this reader supports the <code>mark</code> operation. This
* This always returns <code>true</code> for <code>DocumentReader</code>. * always returns <code>true</code> for <code>DocumentReader</code>.
*/ */
@Override @Override
public boolean markSupported() { public boolean markSupported() {
return true; return true;
} }
/** /**
* Reads the single character at the current position in the document. * Reads the single character at the current position in the document.
*/ */
@@ -96,31 +95,27 @@ public class DocumentReader extends Reader {
return -1; return -1;
} }
} }
/** /**
* Read <code>array.length</code> characters from the beginning * Read <code>array.length</code> characters from the beginning of the document
* of the document into <code>array</code>. * into <code>array</code>.
* *
* @param array * @param array The array to read characters into.
* The array to read characters into.
* @return The number of characters read. * @return The number of characters read.
*/ */
@Override @Override
public int read(char[] array) { public int read(char[] array) {
return read(array, 0, array.length); return read(array, 0, array.length);
} }
/** /**
* Reads characters into a portion of an array. * Reads characters into a portion of an array.
* *
* @param cbuf * @param cbuf The destination buffer.
* The destination buffer. * @param off Offset at which to start storing characters.
* @param off * @param len Maximum number of characters to read.
* Offset at which to start storing characters. * @return The number of characters read, or <code>-1</code> if the end of the
* @param len * stream (document) has been reached.
* Maximum number of characters to read.
* @return The number of characters read, or <code>-1</code> if the
* end of the stream (document) has been reached.
*/ */
@Override @Override
public int read(char[] cbuf, int off, int len) { public int read(char[] cbuf, int off, int len) {
@@ -145,24 +140,23 @@ public class DocumentReader extends Reader {
return -1; return -1;
} }
} }
/** /**
* Tells whether this reader is ready to be read without * Tells whether this reader is ready to be read without blocking for input.
* blocking for input. <code>DocumentReader</code> will * <code>DocumentReader</code> will always return true.
* always return true.
* *
* @return <code>true</code> if the next read operation will * @return <code>true</code> if the next read operation will return without
* return without blocking. * blocking.
*/ */
@Override @Override
public boolean ready() { public boolean ready() {
return true; return true;
} }
/** /**
* Resets the stream. If the stream has been marked, then attempt to * Resets the stream. If the stream has been marked, then attempt to reposition
* reposition it at the mark. If the stream has not been marked, then * it at the mark. If the stream has not been marked, then move it to the
* move it to the beginning of the document. * beginning of the document.
*/ */
@Override @Override
public void reset() { public void reset() {
@@ -173,12 +167,11 @@ public class DocumentReader extends Reader {
mark = -1; mark = -1;
} }
} }
/** /**
* Skips characters. This will not 'skip' past the end of the document. * Skips characters. This will not 'skip' past the end of the document.
* *
* @param n * @param n The number of characters to skip.
* The number of characters to skip.
* @return The number of characters actually skipped. * @return The number of characters actually skipped.
*/ */
@Override @Override
@@ -191,14 +184,13 @@ public class DocumentReader extends Reader {
position = document.getLength(); position = document.getLength();
return document.getLength() - temp; return document.getLength() - temp;
} }
/** /**
* Move to the specified position in the document. If <code>pos</code> * Move to the specified position in the document. If <code>pos</code> is
* is greater than the document's length, the stream's position is moved * greater than the document's length, the stream's position is moved to the end
* to the end of the document. * of the document.
* *
* @param pos * @param pos The position in the document to move to.
* The position in the document to move to.
*/ */
public void seek(long pos) { public void seek(long pos) {
position = Math.min(pos, document.getLength()); position = Math.min(pos, document.getLength());
+47 -73
View File
@@ -28,12 +28,11 @@ import java.io.Writer;
* @version 0.7 * @version 0.7
*/ */
public class UnicodeWriter extends Writer { public class UnicodeWriter extends Writer {
/** /**
* If this system property evaluates to "<code>false</code>", ignoring * If this system property evaluates to "<code>false</code>", ignoring case,
* case, files written out as UTF-8 will not have a BOM written for them. * files written out as UTF-8 will not have a BOM written for them. Otherwise
* Otherwise (even if the property is not set), UTF-8 files will have a * (even if the property is not set), UTF-8 files will have a BOM written.
* BOM written.
*/ */
public static final String PROPERTY_WRITE_UTF8_BOM = "UnicodeWriter.writeUtf8BOM"; public static final String PROPERTY_WRITE_UTF8_BOM = "UnicodeWriter.writeUtf8BOM";
/** /**
@@ -45,73 +44,62 @@ public class UnicodeWriter extends Writer {
private static final byte[] UTF16BE_BOM = new byte[] { (byte) 0xFE, (byte) 0xFF }; private static final byte[] UTF16BE_BOM = new byte[] { (byte) 0xFE, (byte) 0xFF };
private static final byte[] UTF32LE_BOM = new byte[] { (byte) 0xFF, (byte) 0xFE, (byte) 0x00, (byte) 0x00 }; private static final byte[] UTF32LE_BOM = new byte[] { (byte) 0xFF, (byte) 0xFE, (byte) 0x00, (byte) 0x00 };
private static final byte[] UTF32BE_BOM = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0xFE, (byte) 0xFF }; private static final byte[] UTF32BE_BOM = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0xFE, (byte) 0xFF };
/** /**
* This is a utility constructor since the vast majority of the time, this * This is a utility constructor since the vast majority of the time, this class
* class will be used to write Unicode files. * will be used to write Unicode files.
* *
* @param fileName * @param fileName The file to which to write the Unicode output.
* The file to which to write the Unicode output. * @param encoding The encoding to use.
* @param encoding * @throws IOException If an IO exception occurs.
* The encoding to use.
* @throws IOException
* If an IO exception occurs.
*/ */
public UnicodeWriter(String fileName, String encoding) throws IOException { public UnicodeWriter(String fileName, String encoding) throws IOException {
this(new FileOutputStream(fileName), encoding); this(new FileOutputStream(fileName), encoding);
} }
/** /**
* This is a utility constructor since the vast majority of the time, this * This is a utility constructor since the vast majority of the time, this class
* class will be used to write Unicode files. * will be used to write Unicode files.
* *
* @param file * @param file The file to which to write the Unicode output.
* The file to which to write the Unicode output. * @param encoding The encoding to use.
* @param encoding * @throws IOException If an IO exception occurs.
* The encoding to use.
* @throws IOException
* If an IO exception occurs.
*/ */
public UnicodeWriter(File file, String encoding) throws IOException { public UnicodeWriter(File file, String encoding) throws IOException {
this(new FileOutputStream(file), encoding); this(new FileOutputStream(file), encoding);
} }
/** /**
* Creates a new writer. * Creates a new writer.
* *
* @param out * @param out The output stream to write.
* The output stream to write. * @param encoding The encoding to use.
* @param encoding * @throws IOException If an IO exception occurs.
* The encoding to use.
* @throws IOException
* If an IO exception occurs.
*/ */
public UnicodeWriter(OutputStream out, String encoding) throws IOException { public UnicodeWriter(OutputStream out, String encoding) throws IOException {
init(out, encoding); init(out, encoding);
} }
/** /**
* Closes this writer. * Closes this writer.
* *
* @throws IOException * @throws IOException If an IO exception occurs.
* If an IO exception occurs.
*/ */
@Override @Override
public void close() throws IOException { public void close() throws IOException {
internalOut.close(); internalOut.close();
} }
/** /**
* Flushes the stream. * Flushes the stream.
* *
* @throws IOException * @throws IOException If an IO exception occurs.
* If an IO exception occurs.
*/ */
@Override @Override
public void flush() throws IOException { public void flush() throws IOException {
internalOut.flush(); internalOut.flush();
} }
/** /**
* Returns the encoding being used to write this output stream (i.e., the * Returns the encoding being used to write this output stream (i.e., the
* encoding of the file). * encoding of the file).
@@ -121,7 +109,7 @@ public class UnicodeWriter extends Writer {
public String getEncoding() { public String getEncoding() {
return internalOut.getEncoding(); return internalOut.getEncoding();
} }
/** /**
* Returns whether UTF-8 files should have a BOM in them when written. * Returns whether UTF-8 files should have a BOM in them when written.
* *
@@ -137,17 +125,14 @@ public class UnicodeWriter extends Writer {
} }
return true; return true;
} }
/** /**
* Initializes the internal output stream and writes the BOM if the * Initializes the internal output stream and writes the BOM if the specified
* specified encoding is a Unicode encoding. * encoding is a Unicode encoding.
* *
* @param out * @param out The output stream we are writing.
* The output stream we are writing. * @param encoding The encoding in which to write.
* @param encoding * @throws IOException If an I/O error occurs while writing a BOM.
* The encoding in which to write.
* @throws IOException
* If an I/O error occurs while writing a BOM.
*/ */
private void init(OutputStream out, String encoding) throws IOException { private void init(OutputStream out, String encoding) throws IOException {
internalOut = new OutputStreamWriter(out, encoding); internalOut = new OutputStreamWriter(out, encoding);
@@ -169,60 +154,49 @@ public class UnicodeWriter extends Writer {
out.write(UTF32BE_BOM, 0, UTF32BE_BOM.length); out.write(UTF32BE_BOM, 0, UTF32BE_BOM.length);
} }
} }
/** /**
* Sets whether UTF-8 files should have a BOM written in them. * Sets whether UTF-8 files should have a BOM written in them.
* *
* @param write * @param write Whether to write a BOM.
* Whether to write a BOM.
* @see #getWriteUtf8BOM() * @see #getWriteUtf8BOM()
* @see UnicodeWriter * @see UnicodeWriter
*/ */
public static void setWriteUtf8BOM(boolean write) { public static void setWriteUtf8BOM(boolean write) {
System.setProperty(UnicodeWriter.PROPERTY_WRITE_UTF8_BOM, Boolean.toString(write)); System.setProperty(UnicodeWriter.PROPERTY_WRITE_UTF8_BOM, Boolean.toString(write));
} }
/** /**
* Writes a portion of an array of characters. * Writes a portion of an array of characters.
* *
* @param cbuf * @param cbuf The buffer of characters.
* The buffer of characters. * @param off The offset from which to start writing characters.
* @param off * @param len The number of characters to write.
* The offset from which to start writing characters. * @throws IOException If an I/O error occurs.
* @param len
* The number of characters to write.
* @throws IOException
* If an I/O error occurs.
*/ */
@Override @Override
public void write(char[] cbuf, int off, int len) throws IOException { public void write(char[] cbuf, int off, int len) throws IOException {
internalOut.write(cbuf, off, len); internalOut.write(cbuf, off, len);
} }
/** /**
* Writes a single character. * Writes a single character.
* *
* @param c * @param c An integer specifying the character to write.
* An integer specifying the character to write. * @throws IOException If an IO error occurs.
* @throws IOException
* If an IO error occurs.
*/ */
@Override @Override
public void write(int c) throws IOException { public void write(int c) throws IOException {
internalOut.write(c); internalOut.write(c);
} }
/** /**
* Writes a portion of a string. * Writes a portion of a string.
* *
* @param str * @param str The string from which to write.
* The string from which to write. * @param off The offset from which to start writing characters.
* @param off * @param len The number of characters to write.
* The offset from which to start writing characters. * @throws IOException If an IO error occurs.
* @param len
* The number of characters to write.
* @throws IOException
* If an IO error occurs.
*/ */
@Override @Override
public void write(String str, int off, int len) throws IOException { public void write(String str, int off, int len) throws IOException {
+65 -88
View File
@@ -30,7 +30,7 @@ import javax.swing.text.Utilities;
* @version 1.0 * @version 1.0
*/ */
public abstract class RPrintUtilities { public abstract class RPrintUtilities {
private static int currentDocLineNumber; // The line number in the document private static int currentDocLineNumber; // The line number in the document
// we are currently on. // we are currently on.
private static int numDocLines; // The number of lines in the current private static int numDocLines; // The number of lines in the current
@@ -52,27 +52,21 @@ public abstract class RPrintUtilities {
* The metrics of the font currently being used to print. * The metrics of the font currently being used to print.
*/ */
private static FontMetrics fm; private static FontMetrics fm;
/** /**
* Returns the position closest to, but before, position * Returns the position closest to, but before, position
* <code>maxCharsPerLine</code> in * <code>maxCharsPerLine</code> in <code>line</code> of one of the chars in
* <code>line</code> of one of the chars in <code>breakChars</code>, or * <code>breakChars</code>, or simply returns <code>maxCharsPerLine-1</code> if
* simply returns * none of the <code>breakChars</code> comes before that position. This position
* <code>maxCharsPerLine-1</code> if none of the <code>breakChars</code> * represents the logical line break for this <code>java.lang.String</code> if
* comes before * it is being printed in a monospaced font when lines can only be
* that position. This position represents the logical line break for this * <code>maxCharsPerLine</code> characters long.
* <code>java.lang.String</code>
* if it is being printed in a monospaced font when lines can only be
* <code>maxCharsPerLine</code>
* characters long.
* *
* @param line * @param line The text being printed.
* The text being printed. * @param maxCharsPerLine Only up-to this many characters from <code>line</code>
* @param maxCharsPerLine * can be printed on one line.
* Only up-to this many characters from * @return The logical position at which to stop printing <code>line</code> to
* <code>line</code> can be printed on one line. * simulate word wrap.
* @return The logical position at which to stop printing <code>line</code>
* to simulate word wrap.
*/ */
private static int getLineBreakPoint(String line, final int maxCharsPerLine) { private static int getLineBreakPoint(String line, final int maxCharsPerLine) {
int breakPoint = -1; int breakPoint = -1;
@@ -84,30 +78,23 @@ public abstract class RPrintUtilities {
} }
return (breakPoint == -1 ? maxCharsPerLine - 1 : breakPoint); return (breakPoint == -1 ? maxCharsPerLine - 1 : breakPoint);
} }
/** /**
* Prints a <code>Document</code> using a monospaced font, and does no word * Prints a <code>Document</code> using a monospaced font, and does no word
* wrapping (ie, * wrapping (ie, words will wrap mid-word to the next line). This method is
* words will wrap mid-word to the next line). This method is expected to be * expected to be called from Printable 'print(Graphics g)' functions.
* called from
* Printable 'print(Graphics g)' functions.
* *
* @param g * @param g The graphics context to write to.
* The graphics context to write to. * @param doc The <code>javax.swing.text.Document</code> to print.
* @param doc * @param fontSize the point size to use for the monospaced font.
* The <code>javax.swing.text.Document</code> to print. * @param pageIndex The page number to print.
* @param fontSize * @param pageFormat The format to print the page with.
* the point size to use for the monospaced font. * @param tabSize The number of spaces to expand tabs to.
* @param pageIndex
* The page number to print.
* @param pageFormat
* The format to print the page with.
* @param tabSize
* The number of spaces to expand tabs to.
* *
* @see #printDocumentMonospacedWordWrap * @see #printDocumentMonospacedWordWrap
*/ */
public static int printDocumentMonospaced(Graphics g, Document doc, int fontSize, int pageIndex, PageFormat pageFormat, int tabSize) { public static int printDocumentMonospaced(Graphics g, Document doc, int fontSize, int pageIndex,
PageFormat pageFormat, int tabSize) {
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.setFont(new Font("Monospaced", Font.PLAIN, fontSize)); g.setFont(new Font("Monospaced", Font.PLAIN, fontSize));
// Initialize our static variables (these are used by our tab expander // Initialize our static variables (these are used by our tab expander
@@ -202,29 +189,23 @@ public abstract class RPrintUtilities {
} }
return Printable.NO_SUCH_PAGE; return Printable.NO_SUCH_PAGE;
} }
/** /**
* Prints a <code>Document</code> using a monospaced font, word wrapping on * Prints a <code>Document</code> using a monospaced font, word wrapping on the
* the characters ' ', '\t', '\n', ',', '.', and ';'. This method is * characters ' ', '\t', '\n', ',', '.', and ';'. This method is expected to be
* expected to be called from Printable 'print(Graphics g)' functions. * called from Printable 'print(Graphics g)' functions.
* *
* @param g * @param g The graphics context to write to.
* The graphics context to write to. * @param doc The <code>javax.swing.text.Document</code> to print.
* @param doc * @param fontSize the point size to use for the monospaced font.
* The <code>javax.swing.text.Document</code> to print. * @param pageIndex The page number to print.
* @param fontSize * @param pageFormat The format to print the page with.
* the point size to use for the monospaced font. * @param tabSize The number of spaces to expand tabs to.
* @param pageIndex
* The page number to print.
* @param pageFormat
* The format to print the page with.
* @param tabSize
* The number of spaces to expand tabs to.
* *
* @see #printDocumentMonospaced * @see #printDocumentMonospaced
*/ */
public static int printDocumentMonospacedWordWrap(Graphics g, Document doc, int fontSize, int pageIndex, PageFormat pageFormat, public static int printDocumentMonospacedWordWrap(Graphics g, Document doc, int fontSize, int pageIndex,
int tabSize) { PageFormat pageFormat, int tabSize) {
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.setFont(new Font("Monospaced", Font.PLAIN, fontSize)); g.setFont(new Font("Monospaced", Font.PLAIN, fontSize));
// Initialize our static variables (these are used by our tab expander // Initialize our static variables (these are used by our tab expander
@@ -320,30 +301,24 @@ public abstract class RPrintUtilities {
} }
return Printable.NO_SUCH_PAGE; return Printable.NO_SUCH_PAGE;
} }
/** /**
* Prints a <code>Document</code> using the specified font, word wrapping * Prints a <code>Document</code> using the specified font, word wrapping on the
* on the characters ' ', '\t', '\n', ',', '.', and ';'. This method is * characters ' ', '\t', '\n', ',', '.', and ';'. This method is expected to be
* expected to be called from Printable 'print(Graphics g)' functions. * called from Printable 'print(Graphics g)' functions.
* *
* @param g * @param g The graphics context to write to.
* The graphics context to write to. * @param textComponent The <code>javax.swing.text.JTextComponent</code> whose
* @param textComponent * text you're printing.
* The <code>javax.swing.text.JTextComponent</code> * @param font The font to use for printing. If <code>null</code>, then
* whose text you're printing. * <code>textComponent</code>'s font is used.
* @param font * @param pageIndex The page number to print.
* The font to use for printing. If <code>null</code>, then * @param pageFormat The format to print the page with.
* <code>textComponent</code>'s font is used. * @param tabSize The number of spaces to convert tabs to.
* @param pageIndex
* The page number to print.
* @param pageFormat
* The format to print the page with.
* @param tabSize
* The number of spaces to convert tabs to.
* *
*/ */
public static int printDocumentWordWrap(Graphics g, JTextComponent textComponent, Font font, int pageIndex, PageFormat pageFormat, public static int printDocumentWordWrap(Graphics g, JTextComponent textComponent, Font font, int pageIndex,
int tabSize) { PageFormat pageFormat, int tabSize) {
// Initialize our graphics object. // Initialize our graphics object.
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.setFont(font != null ? font : textComponent.getFont()); g.setFont(font != null ? font : textComponent.getFont());
@@ -389,7 +364,8 @@ public abstract class RPrintUtilities {
// we'd start after the part // we'd start after the part
// that has already been printed). // that has already been printed).
try { try {
doc.getText(currentLineStart + startingOffset, currentLineEnd - (currentLineStart + startingOffset), currentLineSeg); doc.getText(currentLineStart + startingOffset, currentLineEnd - (currentLineStart + startingOffset),
currentLineSeg);
} catch (BadLocationException ble) { } catch (BadLocationException ble) {
System.err.println("BadLocationException in print (where there shouldn't be one!): " + ble); System.err.println("BadLocationException in print (where there shouldn't be one!): " + ble);
return Printable.NO_SUCH_PAGE; return Printable.NO_SUCH_PAGE;
@@ -452,7 +428,8 @@ public abstract class RPrintUtilities {
System.err.println(ble); System.err.println(ble);
return Printable.NO_SUCH_PAGE; return Printable.NO_SUCH_PAGE;
} }
currentLineLengthInPixels = Utilities.getTabbedTextWidth(currentLineSeg, fm, 0, tabExpander, 0); currentLineLengthInPixels = Utilities.getTabbedTextWidth(currentLineSeg, fm, 0, tabExpander,
0);
} while (currentLineLengthInPixels <= lineLengthInPixels); } while (currentLineLengthInPixels <= lineLengthInPixels);
currentPos--; currentPos--;
} }
@@ -460,8 +437,8 @@ public abstract class RPrintUtilities {
doc.getText((currentLineStart + startingOffset), currentPos, currentLineSeg); doc.getText((currentLineStart + startingOffset), currentPos, currentLineSeg);
} catch (BadLocationException ble) { } catch (BadLocationException ble) {
System.err.println("BadLocationException in print (a):"); System.err.println("BadLocationException in print (a):");
System.err.println("==> currentLineStart: " + currentLineStart + "; startingOffset: " + startingOffset System.err.println("==> currentLineStart: " + currentLineStart + "; startingOffset: "
+ "; currentPos: " + currentPos); + startingOffset + "; currentPos: " + currentPos);
System.err.println("==> Range: " + (currentLineStart + startingOffset) + " - " System.err.println("==> Range: " + (currentLineStart + startingOffset) + " - "
+ (currentLineStart + startingOffset + currentPos)); + (currentLineStart + startingOffset + currentPos));
ble.printStackTrace(); ble.printStackTrace();
@@ -491,12 +468,11 @@ public abstract class RPrintUtilities {
} }
return Printable.NO_SUCH_PAGE; return Printable.NO_SUCH_PAGE;
} }
/** /**
* Removes any spaces or tabs from the end of the segment. * Removes any spaces or tabs from the end of the segment.
* *
* @param segment * @param segment The segment from which to remove tailing whitespace.
* The segment from which to remove tailing whitespace.
* @return <code>segment</code> with trailing whitespace removed. * @return <code>segment</code> with trailing whitespace removed.
*/ */
private static Segment removeEndingWhitespace(Segment segment) { private static Segment removeEndingWhitespace(Segment segment) {
@@ -510,15 +486,16 @@ public abstract class RPrintUtilities {
String newStringVal = stringVal.substring(0, stringVal.length() - toTrim); String newStringVal = stringVal.substring(0, stringVal.length() - toTrim);
return new Segment(newStringVal.toCharArray(), 0, newStringVal.length()); return new Segment(newStringVal.toCharArray(), 0, newStringVal.length());
} }
/** /**
* A tab expander for the document currently being printed with the * A tab expander for the document currently being printed with the font being
* font being used for the printing. * used for the printing.
*/ */
private static class RPrintTabExpander implements TabExpander { private static class RPrintTabExpander implements TabExpander {
RPrintTabExpander() {} RPrintTabExpander() {
}
@Override @Override
public float nextTabStop(float x, int tabOffset) { public float nextTabStop(float x, int tabOffset) {
if (tabSizeInSpaces == 0) { if (tabSizeInSpaces == 0) {
@@ -17,17 +17,17 @@ import javax.swing.text.JTextComponent;
* lexicographically (ignoring case). * lexicographically (ignoring case).
* <p> * <p>
* *
* This implementation assumes the input text and replacement text are the * This implementation assumes the input text and replacement text are the same
* same value. It also returns the input text from its {@link #toString()} * value. It also returns the input text from its {@link #toString()} method
* method (which is what <code>DefaultListCellRenderer</code> uses to render * (which is what <code>DefaultListCellRenderer</code> uses to render objects).
* objects). Subclasses that wish to override any of this behavior can simply * Subclasses that wish to override any of this behavior can simply override the
* override the corresponding method(s) needed to do so. * corresponding method(s) needed to do so.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public abstract class AbstractCompletion implements Completion { public abstract class AbstractCompletion implements Completion {
/** /**
* The provider that created this completion; * The provider that created this completion;
*/ */
@@ -38,35 +38,32 @@ public abstract class AbstractCompletion implements Completion {
private Icon icon; private Icon icon;
/** /**
* The relevance of this completion. Completion instances with higher * The relevance of this completion. Completion instances with higher
* "relevance" values are inserted higher into the list of possible * "relevance" values are inserted higher into the list of possible completions
* completions than those with lower values. Completion instances with * than those with lower values. Completion instances with equal relevance
* equal relevance values are sorted alphabetically. * values are sorted alphabetically.
*/ */
private int relevance; private int relevance;
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The provider that created this completion.
* The provider that created this completion.
*/ */
protected AbstractCompletion(CompletionProvider provider) { protected AbstractCompletion(CompletionProvider provider) {
this.provider = provider; this.provider = provider;
} }
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The provider that created this completion.
* The provider that created this completion. * @param icon The icon for this completion.
* @param icon
* The icon for this completion.
*/ */
protected AbstractCompletion(CompletionProvider provider, Icon icon) { protected AbstractCompletion(CompletionProvider provider, Icon icon) {
this(provider); this(provider);
setIcon(icon); setIcon(icon);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -79,7 +76,7 @@ public abstract class AbstractCompletion implements Completion {
} }
return -1; return -1;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -87,7 +84,7 @@ public abstract class AbstractCompletion implements Completion {
public String getAlreadyEntered(JTextComponent comp) { public String getAlreadyEntered(JTextComponent comp) {
return provider.getAlreadyEnteredText(comp); return provider.getAlreadyEnteredText(comp);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -95,10 +92,10 @@ public abstract class AbstractCompletion implements Completion {
public Icon getIcon() { public Icon getIcon() {
return icon; return icon;
} }
/** /**
* Returns the text the user has to (start) typing for this completion * Returns the text the user has to (start) typing for this completion to be
* to be offered. The default implementation simply returns * offered. The default implementation simply returns
* {@link #getReplacementText()}. * {@link #getReplacementText()}.
* *
* @return The text the user has to (start) typing for this completion. * @return The text the user has to (start) typing for this completion.
@@ -108,7 +105,7 @@ public abstract class AbstractCompletion implements Completion {
public String getInputText() { public String getInputText() {
return getReplacementText(); return getReplacementText();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -116,7 +113,7 @@ public abstract class AbstractCompletion implements Completion {
public CompletionProvider getProvider() { public CompletionProvider getProvider() {
return provider; return provider;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -124,10 +121,10 @@ public abstract class AbstractCompletion implements Completion {
public int getRelevance() { public int getRelevance() {
return relevance; return relevance;
} }
/** /**
* The default implementation returns <code>null</code>. Subclasses * The default implementation returns <code>null</code>. Subclasses can override
* can override this method. * this method.
* *
* @return The tool tip text. * @return The tool tip text.
*/ */
@@ -135,29 +132,27 @@ public abstract class AbstractCompletion implements Completion {
public String getToolTipText() { public String getToolTipText() {
return null; return null;
} }
/** /**
* Sets the icon to use for this completion. * Sets the icon to use for this completion.
* *
* @param icon * @param icon The icon to use.
* The icon to use.
* @see #getIcon() * @see #getIcon()
*/ */
public void setIcon(Icon icon) { public void setIcon(Icon icon) {
this.icon = icon; this.icon = icon;
} }
/** /**
* Sets the relevance of this completion. * Sets the relevance of this completion.
* *
* @param relevance * @param relevance The new relevance of this completion.
* The new relevance of this completion.
* @see #getRelevance() * @see #getRelevance()
*/ */
public void setRelevance(int relevance) { public void setRelevance(int relevance) {
this.relevance = relevance; this.relevance = relevance;
} }
/** /**
* Returns a string representation of this completion. The default * Returns a string representation of this completion. The default
* implementation returns {@link #getInputText()}. * implementation returns {@link #getInputText()}.
@@ -43,14 +43,14 @@ import javax.swing.event.HyperlinkListener;
import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator; import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator;
/** /**
* The optional "description" window that describes the currently selected * The optional "description" window that describes the currently selected item
* item in the auto-completion window. * in the auto-completion window.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescWindowCallback { class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescWindowCallback {
/** /**
* The parent AutoCompletion instance. * The parent AutoCompletion instance.
*/ */
@@ -89,9 +89,8 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
private int historyPos; private int historyPos;
/** /**
* Provides a slight delay between asking to set a description and actually * Provides a slight delay between asking to set a description and actually
* displaying it, so that if the user is scrolling quickly through * displaying it, so that if the user is scrolling quickly through completions,
* completions, those with slow-to-calculate summaries won't bog down the * those with slow-to-calculate summaries won't bog down the scrolling.
* scrolling.
*/ */
private Timer timer; private Timer timer;
/** /**
@@ -103,24 +102,21 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
*/ */
private ResourceBundle bundle; private ResourceBundle bundle;
/** /**
* The amount of time to wait after the user changes the selected * The amount of time to wait after the user changes the selected completion to
* completion to refresh the description. This delay is in place to help * refresh the description. This delay is in place to help performance for
* performance for {@link Completion}s that may be slow to compute their * {@link Completion}s that may be slow to compute their summary text.
* summary text.
*/ */
private static final int INITIAL_TIMER_DELAY = 120; private static final int INITIAL_TIMER_DELAY = 120;
/** /**
* The resource bundle name. * The resource bundle name.
*/ */
private static final String MSG = "org.fife.ui.autocomplete.AutoCompleteDescWindow"; private static final String MSG = "org.fife.ui.autocomplete.AutoCompleteDescWindow";
/** /**
* Constructor. * Constructor.
* *
* @param owner * @param owner The parent window.
* The parent window. * @param ac The parent auto-completion.
* @param ac
* The parent auto-completion.
*/ */
public AutoCompleteDescWindow(Window owner, AutoCompletion ac) { public AutoCompleteDescWindow(Window owner, AutoCompletion ac) {
super(owner); super(owner);
@@ -146,12 +142,12 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
descWindowNavBar.add(new JButton(forwardAction)); descWindowNavBar.add(new JButton(forwardAction));
bottomPanel = new JPanel(new BorderLayout()); bottomPanel = new JPanel(new BorderLayout());
b = new AbstractBorder() { b = new AbstractBorder() {
@Override @Override
public Insets getBorderInsets(Component c) { public Insets getBorderInsets(Component c) {
return new Insets(1, 0, 0, 0); return new Insets(1, 0, 0, 0);
} }
@Override @Override
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
g.setColor(UIManager.getColor("controlDkShadow")); g.setColor(UIManager.getColor("controlDkShadow"));
@@ -179,19 +175,18 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
timer = new Timer(INITIAL_TIMER_DELAY, timerAction); timer = new Timer(INITIAL_TIMER_DELAY, timerAction);
timer.setRepeats(false); timer.setRepeats(false);
} }
/** /**
* Sets the currently displayed description and updates the history. * Sets the currently displayed description and updates the history.
* *
* @param historyItem * @param historyItem The item to add to the history.
* The item to add to the history.
*/ */
private void addToHistory(HistoryEntry historyItem) { private void addToHistory(HistoryEntry historyItem) {
history.add(++historyPos, historyItem); history.add(++historyPos, historyItem);
clearHistoryAfterCurrentPos(); clearHistoryAfterCurrentPos();
setActionStates(); setActionStates();
} }
/** /**
* Clears the history of viewed descriptions. * Clears the history of viewed descriptions.
*/ */
@@ -202,7 +197,7 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
setActionStates(); setActionStates();
} }
} }
/** /**
* Makes the current history page the last one in the history. * Makes the current history page the last one in the history.
*/ */
@@ -212,10 +207,10 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
} }
setActionStates(); setActionStates();
} }
/** /**
* Copies from the description text area, if it is visible and there is * Copies from the description text area, if it is visible and there is a
* a selection. * selection.
* *
* @return Whether a copy occurred. * @return Whether a copy occurred.
*/ */
@@ -226,12 +221,11 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
} }
return false; return false;
} }
/** /**
* Returns the localized message for the specified key. * Returns the localized message for the specified key.
* *
* @param key * @param key The key.
* The key.
* @return The localized message. * @return The localized message.
*/ */
private String getString(String key) { private String getString(String key) {
@@ -240,12 +234,11 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
} }
return bundle.getString(key); return bundle.getString(key);
} }
/** /**
* Called when a hyperlink is clicked. * Called when a hyperlink is clicked.
* *
* @param e * @param e The event.
* The event.
*/ */
@Override @Override
public void hyperlinkUpdate(HyperlinkEvent e) { public void hyperlinkUpdate(HyperlinkEvent e) {
@@ -261,7 +254,8 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
URL newUrl = redirector.possiblyRedirect(url); URL newUrl = redirector.possiblyRedirect(url);
if (newUrl != null && newUrl != url) { if (newUrl != null && newUrl != url) {
url = newUrl; url = newUrl;
e = new HyperlinkEvent(e.getSource(), e.getEventType(), newUrl, e.getDescription(), e.getSourceElement()); e = new HyperlinkEvent(e.getSource(), e.getEventType(), newUrl, e.getDescription(),
e.getSourceElement());
} }
} }
} }
@@ -300,7 +294,7 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
} }
} }
} }
/** /**
* Enables or disables the back and forward actions as appropriate. * Enables or disables the back and forward actions as appropriate.
*/ */
@@ -323,47 +317,41 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
} }
forwardAction.putValue(Action.SHORT_DESCRIPTION, desc); forwardAction.putValue(Action.SHORT_DESCRIPTION, desc);
} }
/** /**
* Sets the description displayed in this window. This clears the * Sets the description displayed in this window. This clears the history.
* history.
* *
* @param item * @param item The item whose description you want to display.
* The item whose description you want to display.
*/ */
public void setDescriptionFor(Completion item) { public void setDescriptionFor(Completion item) {
setDescriptionFor(item, false); setDescriptionFor(item, false);
} }
/** /**
* Sets the description displayed in this window. * Sets the description displayed in this window.
* *
* @param item * @param item The item whose description you want to display.
* The item whose description you want to display. * @param addToHistory Whether to add this page to the page history (as opposed
* @param addToHistory * to clearing it and starting anew).
* Whether to add this page to the page history
* (as opposed to clearing it and starting anew).
*/ */
protected void setDescriptionFor(Completion item, boolean addToHistory) { protected void setDescriptionFor(Completion item, boolean addToHistory) {
setDescriptionFor(item, null, addToHistory); setDescriptionFor(item, null, addToHistory);
} }
/** /**
* Sets the description displayed in this window. * Sets the description displayed in this window.
* *
* @param item * @param item The item whose description you want to display.
* The item whose description you want to display.
* @parma anchor The anchor to jump to, or <code>null</code> if none. * @parma anchor The anchor to jump to, or <code>null</code> if none.
* @param addToHistory * @param addToHistory Whether to add this page to the page history (as opposed
* Whether to add this page to the page history * to clearing it and starting anew).
* (as opposed to clearing it and starting anew).
*/ */
protected void setDescriptionFor(Completion item, String anchor, boolean addToHistory) { protected void setDescriptionFor(Completion item, String anchor, boolean addToHistory) {
timer.stop(); timer.stop();
timerAction.setCompletion(item, anchor, addToHistory); timerAction.setCompletion(item, anchor, addToHistory);
timer.start(); timer.start();
} }
private void setDisplayedDesc(Completion completion, final String anchor, boolean addToHistory) { private void setDisplayedDesc(Completion completion, final String anchor, boolean addToHistory) {
String desc = completion == null ? null : completion.getSummary(); String desc = completion == null ? null : completion.getSummary();
if (desc == null) { if (desc == null) {
@@ -372,7 +360,7 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
descArea.setText(desc); descArea.setText(desc);
if (anchor != null) { if (anchor != null) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
descArea.scrollToReference(anchor); descArea.scrollToReference(anchor);
@@ -388,7 +376,7 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
} }
addToHistory(new HistoryEntry(completion, desc, null)); addToHistory(new HistoryEntry(completion, desc, null));
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -399,21 +387,19 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
} }
super.setVisible(visible); super.setVisible(visible);
} }
/** /**
* Callback for custom <code>ExternalURLHandler</code>s. * Callback for custom <code>ExternalURLHandler</code>s.
* *
* @param completion * @param completion The completion to display.
* The completion to display. * @param anchor The anchor in the HTML to jump to, or <code>null</code> if
* @param anchor * none.
* The anchor in the HTML to jump to, or <code>null</code>
* if none.
*/ */
@Override @Override
public void showSummaryFor(Completion completion, String anchor) { public void showSummaryFor(Completion completion, String anchor) {
setDescriptionFor(completion, anchor, true); setDescriptionFor(completion, anchor, true);
} }
/** /**
* Called by the parent completion popup window the LookAndFeel is updated. * Called by the parent completion popup window the LookAndFeel is updated.
*/ */
@@ -425,25 +411,25 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
scrollPane.getViewport().setBackground(descArea.getBackground()); scrollPane.getViewport().setBackground(descArea.getBackground());
((JPanel) getContentPane()).setBorder(TipUtil.getToolTipBorder()); ((JPanel) getContentPane()).setBorder(TipUtil.getToolTipBorder());
} }
/** /**
* A completion and its cached summary text. * A completion and its cached summary text.
*/ */
private static class HistoryEntry { private static class HistoryEntry {
public Completion completion; public Completion completion;
public String summary; public String summary;
public String anchor; public String anchor;
public HistoryEntry(Completion completion, String summary, String anchor) { public HistoryEntry(Completion completion, String summary, String anchor) {
this.completion = completion; this.completion = completion;
this.summary = summary; this.summary = summary;
this.anchor = anchor; this.anchor = anchor;
} }
/** /**
* Overridden to display a short name for the completion, since it's * Overridden to display a short name for the completion, since it's used in the
* used in the tool tips for the "back" and "forward" buttons. * tool tips for the "back" and "forward" buttons.
* *
* @return A string representation of this history entry. * @return A string representation of this history entry.
*/ */
@@ -452,16 +438,16 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
return completion.getInputText(); return completion.getInputText();
} }
} }
/** /**
* Action that actually updates the summary text displayed. * Action that actually updates the summary text displayed.
*/ */
private class TimerAction extends AbstractAction { private class TimerAction extends AbstractAction {
private Completion completion; private Completion completion;
private String anchor; private String anchor;
private boolean addToHistory; private boolean addToHistory;
/** /**
* Called when the timer is fired. * Called when the timer is fired.
*/ */
@@ -469,26 +455,26 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
setDisplayedDesc(completion, anchor, addToHistory); setDisplayedDesc(completion, anchor, addToHistory);
} }
public void setCompletion(Completion c, String anchor, boolean addToHistory) { public void setCompletion(Completion c, String anchor, boolean addToHistory) {
this.completion = c; this.completion = c;
this.anchor = anchor; this.anchor = anchor;
this.addToHistory = addToHistory; this.addToHistory = addToHistory;
} }
} }
/** /**
* Action that moves to the previous description displayed. * Action that moves to the previous description displayed.
*/ */
class ToolBarBackAction extends AbstractAction { class ToolBarBackAction extends AbstractAction {
public ToolBarBackAction(boolean ltr) { public ToolBarBackAction(boolean ltr) {
String img = "org/fife/ui/autocomplete/arrow_" + (ltr ? "left.png" : "right.png"); String img = "org/fife/ui/autocomplete/arrow_" + (ltr ? "left.png" : "right.png");
ClassLoader cl = getClass().getClassLoader(); ClassLoader cl = getClass().getClassLoader();
Icon icon = new ImageIcon(cl.getResource(img)); Icon icon = new ImageIcon(cl.getResource(img));
putValue(Action.SMALL_ICON, icon); putValue(Action.SMALL_ICON, icon);
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (historyPos > 0) { if (historyPos > 0) {
@@ -504,19 +490,19 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, DescW
} }
} }
} }
/** /**
* Action that moves to the previous description displayed. * Action that moves to the previous description displayed.
*/ */
class ToolBarForwardAction extends AbstractAction { class ToolBarForwardAction extends AbstractAction {
public ToolBarForwardAction(boolean ltr) { public ToolBarForwardAction(boolean ltr) {
String img = "org/fife/ui/autocomplete/arrow_" + (ltr ? "right.png" : "left.png"); String img = "org/fife/ui/autocomplete/arrow_" + (ltr ? "right.png" : "left.png");
ClassLoader cl = getClass().getClassLoader(); ClassLoader cl = getClass().getClassLoader();
Icon icon = new ImageIcon(cl.getResource(img)); Icon icon = new ImageIcon(cl.getResource(img));
putValue(Action.SMALL_ICON, icon); putValue(Action.SMALL_ICON, icon);
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (history != null && historyPos < history.size() - 1) { if (history != null && historyPos < history.size() - 1) {
@@ -43,16 +43,15 @@ import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator;
/** /**
* The actual popup window of choices. When visible, this window intercepts * The actual popup window of choices. When visible, this window intercepts
* certain keystrokes in the parent text component and uses them to navigate * certain keystrokes in the parent text component and uses them to navigate the
* the completion choices instead. If Enter or Escape is pressed, the window * completion choices instead. If Enter or Escape is pressed, the window hides
* hides itself and notifies the {@link AutoCompletion} to insert the selected * itself and notifies the {@link AutoCompletion} to insert the selected text.
* text.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSelectionListener, MouseListener { class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSelectionListener, MouseListener {
/** /**
* The parent AutoCompletion instance. * The parent AutoCompletion instance.
*/ */
@@ -66,27 +65,26 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
*/ */
private CompletionListModel model; private CompletionListModel model;
/** /**
* A hack to work around the fact that we clear our completion model (and * A hack to work around the fact that we clear our completion model (and our
* our selection) when hiding the completion window. This allows us to * selection) when hiding the completion window. This allows us to still know
* still know what the user selected after the popup is hidden. * what the user selected after the popup is hidden.
*/ */
private Completion lastSelection; private Completion lastSelection;
/** /**
* Optional popup window containing a description of the currently * Optional popup window containing a description of the currently selected
* selected completion. * completion.
*/ */
private AutoCompleteDescWindow descWindow; private AutoCompleteDescWindow descWindow;
/** /**
* The preferred size of the optional description window. This field * The preferred size of the optional description window. This field only exists
* only exists because the user may (and usually will) set the size of * because the user may (and usually will) set the size of the description
* the description window before it exists (it must be parented to a * window before it exists (it must be parented to a Window).
* Window).
*/ */
private Dimension preferredDescWindowSize; private Dimension preferredDescWindowSize;
/** /**
* Whether the completion window and the optional description window * Whether the completion window and the optional description window should be
* should be displayed above the current caret position (as opposed to * displayed above the current caret position (as opposed to underneath it,
* underneath it, which is preferred unless there is not enough space). * which is preferred unless there is not enough space).
*/ */
private boolean aboveCaret; private boolean aboveCaret;
private int lastLine; private int lastLine;
@@ -103,7 +101,8 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
private KeyActionPair pageUpKap; private KeyActionPair pageUpKap;
private KeyActionPair pageDownKap; private KeyActionPair pageDownKap;
private KeyActionPair ctrlCKap; private KeyActionPair ctrlCKap;
private KeyActionPair oldEscape, oldUp, oldDown, oldLeft, oldRight, oldEnter, oldTab, oldHome, oldEnd, oldPageUp, oldPageDown, oldCtrlC; private KeyActionPair oldEscape, oldUp, oldDown, oldLeft, oldRight, oldEnter, oldTab, oldHome, oldEnd, oldPageUp,
oldPageDown, oldCtrlC;
/** /**
* The space between the caret and the completion popup. * The space between the caret and the completion popup.
*/ */
@@ -112,14 +111,12 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
* The class name of the Substance List UI. * The class name of the Substance List UI.
*/ */
private static final String SUBSTANCE_LIST_UI = "org.pushingpixels.substance.internal.ui.SubstanceListUI"; private static final String SUBSTANCE_LIST_UI = "org.pushingpixels.substance.internal.ui.SubstanceListUI";
/** /**
* Constructor. * Constructor.
* *
* @param parent * @param parent The parent window (hosting the text component).
* The parent window (hosting the text component). * @param ac The auto-completion instance.
* @param ac
* The auto-completion instance.
*/ */
public AutoCompletePopupWindow(Window parent, final AutoCompletion ac) { public AutoCompletePopupWindow(Window parent, final AutoCompletion ac) {
super(parent); super(parent);
@@ -131,7 +128,8 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
list.addListSelectionListener(this); list.addListSelectionListener(this);
list.addMouseListener(this); list.addMouseListener(this);
JPanel contentPane = new JPanel(new BorderLayout()); JPanel contentPane = new JPanel(new BorderLayout());
JScrollPane sp = new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); JScrollPane sp = new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
// In 1.4, JScrollPane.setCorner() has a bug where it won't accept // In 1.4, JScrollPane.setCorner() has a bug where it won't accept
// JScrollPane.LOWER_TRAILING_CORNER, even though that constant is // JScrollPane.LOWER_TRAILING_CORNER, even though that constant is
// defined. So we have to put the logic added in 1.5 to handle it // defined. So we have to put the logic added in 1.5 to handle it
@@ -155,7 +153,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
setFocusableWindowState(false); setFocusableWindowState(false);
lastLine = -1; lastLine = -1;
} }
@Override @Override
public void caretUpdate(CaretEvent e) { public void caretUpdate(CaretEvent e) {
if (isVisible()) { // Should always be true if (isVisible()) { // Should always be true
@@ -170,7 +168,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
Thread.dumpStack(); Thread.dumpStack();
} }
} }
/** /**
* Creates the description window. * Creates the description window.
* *
@@ -186,10 +184,10 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
dw.setSize(size); dw.setSize(size);
return dw; return dw;
} }
/** /**
* Creates the mappings from keys to Actions we'll be putting into the * Creates the mappings from keys to Actions we'll be putting into the text
* text component's ActionMap and InputMap. * component's ActionMap and InputMap.
*/ */
private void createKeyActionPairs() { private void createKeyActionPairs() {
// Actions we'll install. // Actions we'll install.
@@ -220,11 +218,11 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
oldPageDown = new KeyActionPair(); oldPageDown = new KeyActionPair();
oldCtrlC = new KeyActionPair(); oldCtrlC = new KeyActionPair();
} }
protected void doAutocomplete() { protected void doAutocomplete() {
lastLine = ac.refreshPopupWindow(); lastLine = ac.refreshPopupWindow();
} }
/** /**
* Returns the copy keystroke to use for this platform. * Returns the copy keystroke to use for this platform.
* *
@@ -235,10 +233,10 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
return KeyStroke.getKeyStroke(key, mask); return KeyStroke.getKeyStroke(key, mask);
} }
/** /**
* Returns the default list cell renderer used when a completion provider * Returns the default list cell renderer used when a completion provider does
* does not supply its own. * not supply its own.
* *
* @return The default list cell renderer. * @return The default list cell renderer.
* @see #setListCellRenderer(ListCellRenderer) * @see #setListCellRenderer(ListCellRenderer)
@@ -247,7 +245,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
DelegatingCellRenderer dcr = (DelegatingCellRenderer) list.getCellRenderer(); DelegatingCellRenderer dcr = (DelegatingCellRenderer) list.getCellRenderer();
return dcr.getFallbackCellRenderer(); return dcr.getFallbackCellRenderer();
} }
/** /**
* Returns the selected value, or <code>null</code> if nothing is selected. * Returns the selected value, or <code>null</code> if nothing is selected.
* *
@@ -256,7 +254,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
public Completion getSelection() { public Completion getSelection() {
return isShowing() ? (Completion) list.getSelectedValue() : lastSelection; return isShowing() ? (Completion) list.getSelectedValue() : lastSelection;
} }
/** /**
* Inserts the currently selected completion. * Inserts the currently selected completion.
* *
@@ -266,10 +264,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
Completion comp = getSelection(); Completion comp = getSelection();
ac.insertCompletion(comp); ac.insertCompletion(comp);
} }
/** /**
* Registers keyboard actions to listen for in the text component and * Registers keyboard actions to listen for in the text component and intercept.
* intercept.
* *
* @see #uninstallKeyBindings() * @see #uninstallKeyBindings()
*/ */
@@ -313,30 +310,34 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
comp.addCaretListener(this); comp.addCaretListener(this);
keyBindingsInstalled = true; keyBindingsInstalled = true;
} }
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) { if (e.getClickCount() == 2) {
insertSelectedCompletion(); insertSelectedCompletion();
} }
} }
@Override @Override
public void mouseEntered(MouseEvent e) {} public void mouseEntered(MouseEvent e) {
}
@Override @Override
public void mouseExited(MouseEvent e) {} public void mouseExited(MouseEvent e) {
}
@Override @Override
public void mousePressed(MouseEvent e) {} public void mousePressed(MouseEvent e) {
}
@Override @Override
public void mouseReleased(MouseEvent e) {} public void mouseReleased(MouseEvent e) {
}
/** /**
* Positions the description window relative to the completion choices * Positions the description window relative to the completion choices window.
* window. We assume there is room on one side of the other for this * We assume there is room on one side of the other for this entire window to
* entire window to fit. * fit.
*/ */
private void positionDescWindow() { private void positionDescWindow() {
boolean showDescWindow = descWindow != null && ac.getShowDescWindow(); boolean showDescWindow = descWindow != null && ac.getShowDescWindow();
@@ -372,42 +373,31 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
descWindow.setLocation(x, y); descWindow.setLocation(x, y);
} }
} }
/** /**
* "Puts back" the original key/Action pair for a keystroke. This is used * "Puts back" the original key/Action pair for a keystroke. This is used when
* when this popup is hidden. * this popup is hidden.
* *
* @param im * @param im The input map.
* The input map. * @param am The action map.
* @param am * @param key The keystroke whose key/Action pair to change.
* The action map. * @param kap The (original) key/Action pair.
* @param key * @see #replaceAction(InputMap, ActionMap, int, KeyActionPair, KeyActionPair)
* The keystroke whose key/Action pair to change.
* @param kap
* The (original) key/Action pair.
* @see #replaceAction(InputMap, ActionMap, int, KeyActionPair,
* KeyActionPair)
*/ */
private void putBackAction(InputMap im, ActionMap am, int key, KeyActionPair kap) { private void putBackAction(InputMap im, ActionMap am, int key, KeyActionPair kap) {
KeyStroke ks = KeyStroke.getKeyStroke(key, 0); KeyStroke ks = KeyStroke.getKeyStroke(key, 0);
am.put(im.get(ks), kap.action); // Original action for the "new" key am.put(im.get(ks), kap.action); // Original action for the "new" key
im.put(ks, kap.key); // Original key for the keystroke. im.put(ks, kap.key); // Original key for the keystroke.
} }
/** /**
* Replaces a key/Action pair in an InputMap and ActionMap with a new * Replaces a key/Action pair in an InputMap and ActionMap with a new pair.
* pair.
* *
* @param im * @param im The input map.
* The input map. * @param am The action map.
* @param am * @param key The keystroke whose information to replace.
* The action map. * @param kap The new key/Action pair for <code>key</code>.
* @param key * @param old A buffer in which to place the old key/Action pair.
* The keystroke whose information to replace.
* @param kap
* The new key/Action pair for <code>key</code>.
* @param old
* A buffer in which to place the old key/Action pair.
* @see #putBackAction(InputMap, ActionMap, int, KeyActionPair) * @see #putBackAction(InputMap, ActionMap, int, KeyActionPair)
*/ */
private void replaceAction(InputMap im, ActionMap am, int key, KeyActionPair kap, KeyActionPair old) { private void replaceAction(InputMap im, ActionMap am, int key, KeyActionPair kap, KeyActionPair old) {
@@ -417,7 +407,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
old.action = am.get(kap.key); old.action = am.get(kap.key);
am.put(kap.key, kap.action); am.put(kap.key, kap.action);
} }
/** /**
* Selects the first item in the completion list. * Selects the first item in the completion list.
* *
@@ -429,7 +419,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
list.ensureIndexIsVisible(0); list.ensureIndexIsVisible(0);
} }
} }
/** /**
* Selects the last item in the completion list. * Selects the last item in the completion list.
* *
@@ -442,7 +432,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
list.ensureIndexIsVisible(index); list.ensureIndexIsVisible(index);
} }
} }
/** /**
* Selects the next item in the completion list. * Selects the next item in the completion list.
* *
@@ -456,10 +446,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
list.ensureIndexIsVisible(index); list.ensureIndexIsVisible(index);
} }
} }
/** /**
* Selects the completion item one "page down" from the currently selected * Selects the completion item one "page down" from the currently selected one.
* one.
* *
* @see #selectPageUpItem() * @see #selectPageUpItem()
*/ */
@@ -469,10 +458,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
list.setSelectedIndex(i); list.setSelectedIndex(i);
list.ensureIndexIsVisible(i); list.ensureIndexIsVisible(i);
} }
/** /**
* Selects the completion item one "page up" from the currently selected * Selects the completion item one "page up" from the currently selected one.
* one.
* *
* @see #selectPageDownItem() * @see #selectPageDownItem()
*/ */
@@ -482,7 +470,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
list.setSelectedIndex(i); list.setSelectedIndex(i);
list.ensureIndexIsVisible(i); list.ensureIndexIsVisible(i);
} }
/** /**
* Selects the previous item in the completion list. * Selects the previous item in the completion list.
* *
@@ -491,40 +479,38 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
private void selectPreviousItem() { private void selectPreviousItem() {
int index = list.getSelectedIndex(); int index = list.getSelectedIndex();
switch (index) { switch (index) {
case 0: case 0:
index = list.getModel().getSize() - 1; index = list.getModel().getSize() - 1;
break; break;
case -1: // Check for an empty list (would be an error) case -1: // Check for an empty list (would be an error)
index = list.getModel().getSize() - 1; index = list.getModel().getSize() - 1;
if (index == -1) { if (index == -1) {
return; return;
} }
break; break;
default: default:
index = index - 1; index = index - 1;
break; break;
} }
list.setSelectedIndex(index); list.setSelectedIndex(index);
list.ensureIndexIsVisible(index); list.ensureIndexIsVisible(index);
} }
/** /**
* Sets the completions to display in the choices list. The first * Sets the completions to display in the choices list. The first completion is
* completion is selected. * selected.
* *
* @param completions * @param completions The completions to display.
* The completions to display.
*/ */
public void setCompletions(List<Completion> completions) { public void setCompletions(List<Completion> completions) {
model.setContents(completions); model.setContents(completions);
selectFirstItem(); selectFirstItem();
} }
/** /**
* Sets the size of the description window. * Sets the size of the description window.
* *
* @param size * @param size The new size. This cannot be <code>null</code>.
* The new size. This cannot be <code>null</code>.
*/ */
public void setDescriptionWindowSize(Dimension size) { public void setDescriptionWindowSize(Dimension size) {
if (descWindow != null) { if (descWindow != null) {
@@ -533,28 +519,26 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
preferredDescWindowSize = size; preferredDescWindowSize = size;
} }
} }
/** /**
* Sets the default list cell renderer to use when a completion provider * Sets the default list cell renderer to use when a completion provider does
* does not supply its own. * not supply its own.
* *
* @param renderer * @param renderer The renderer to use. If this is <code>null</code>, a default
* The renderer to use. If this is <code>null</code>, * renderer is used.
* a default renderer is used.
* @see #getListCellRenderer() * @see #getListCellRenderer()
*/ */
public void setListCellRenderer(ListCellRenderer renderer) { public void setListCellRenderer(ListCellRenderer renderer) {
DelegatingCellRenderer dcr = (DelegatingCellRenderer) list.getCellRenderer(); DelegatingCellRenderer dcr = (DelegatingCellRenderer) list.getCellRenderer();
dcr.setFallbackCellRenderer(renderer); dcr.setFallbackCellRenderer(renderer);
} }
/** /**
* Sets the location of this window to be "good" relative to the specified * Sets the location of this window to be "good" relative to the specified
* rectangle. That rectangle should be the location of the text * rectangle. That rectangle should be the location of the text component's
* component's caret, in screen coordinates. * caret, in screen coordinates.
* *
* @param r * @param r The text component's caret position, in screen coordinates.
* The text component's caret position, in screen coordinates.
*/ */
public void setLocationRelativeTo(Rectangle r) { public void setLocationRelativeTo(Rectangle r) {
// Multi-monitor support - make sure the completion window (and // Multi-monitor support - make sure the completion window (and
@@ -596,12 +580,11 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
positionDescWindow(); positionDescWindow();
} }
} }
/** /**
* Toggles the visibility of this popup window. * Toggles the visibility of this popup window.
* *
* @param visible * @param visible Whether this window should be visible.
* Whether this window should be visible.
*/ */
@Override @Override
public void setVisible(boolean visible) { public void setVisible(boolean visible) {
@@ -649,7 +632,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
/** /**
* Stops intercepting certain keystrokes from the text component. * Stops intercepting certain keystrokes from the text component.
* *
@@ -683,10 +666,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
comp.removeCaretListener(this); comp.removeCaretListener(this);
keyBindingsInstalled = false; keyBindingsInstalled = false;
} }
/** /**
* Updates the <tt>LookAndFeel</tt> of this window and the description * Updates the <tt>LookAndFeel</tt> of this window and the description window.
* window.
*/ */
public void updateUI() { public void updateUI() {
SwingUtilities.updateComponentTreeUI(this); SwingUtilities.updateComponentTreeUI(this);
@@ -694,12 +676,11 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
descWindow.updateUI(); descWindow.updateUI();
} }
} }
/** /**
* Called when a new item is selected in the popup list. * Called when a new item is selected in the popup list.
* *
* @param e * @param e The event.
* The event.
*/ */
@Override @Override
public void valueChanged(ListSelectionEvent e) { public void valueChanged(ListSelectionEvent e) {
@@ -711,9 +692,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
class CopyAction extends AbstractAction { class CopyAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
boolean doNormalCopy = false; boolean doNormalCopy = false;
@@ -725,9 +706,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
class DownAction extends AbstractAction { class DownAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
@@ -735,9 +716,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
class EndAction extends AbstractAction { class EndAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
@@ -745,9 +726,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
class EnterAction extends AbstractAction { class EnterAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
@@ -755,9 +736,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
class EscapeAction extends AbstractAction { class EscapeAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
@@ -765,9 +746,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
class HomeAction extends AbstractAction { class HomeAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
@@ -775,25 +756,26 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
/** /**
* A mapping from a key (an Object) to an Action. * A mapping from a key (an Object) to an Action.
*/ */
private static class KeyActionPair { private static class KeyActionPair {
public Object key; public Object key;
public Action action; public Action action;
public KeyActionPair() {} public KeyActionPair() {
}
public KeyActionPair(Object key, Action a) { public KeyActionPair(Object key, Action a) {
this.key = key; this.key = key;
this.action = a; this.action = a;
} }
} }
class LeftAction extends AbstractAction { class LeftAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
@@ -813,9 +795,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
class PageDownAction extends AbstractAction { class PageDownAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
@@ -823,9 +805,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
class PageUpAction extends AbstractAction { class PageUpAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
@@ -833,16 +815,16 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
/** /**
* The actual list of completion choices in this popup window. * The actual list of completion choices in this popup window.
*/ */
private class PopupList extends JList { private class PopupList extends JList {
public PopupList(CompletionListModel model) { public PopupList(CompletionListModel model) {
super(model); super(model);
} }
@Override @Override
public void setUI(ListUI ui) { public void setUI(ListUI ui) {
if (Util.getUseSubstanceRenderers() && SUBSTANCE_LIST_UI.equals(ui.getClass().getName())) { if (Util.getUseSubstanceRenderers() && SUBSTANCE_LIST_UI.equals(ui.getClass().getName())) {
@@ -863,9 +845,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
super.setUI(ui); super.setUI(ui);
} }
} }
class RightAction extends AbstractAction { class RightAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
@@ -885,9 +867,9 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, ListSele
} }
} }
} }
class UpAction extends AbstractAction { class UpAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isVisible()) { if (isVisible()) {
File diff suppressed because it is too large. Load diff
@@ -8,34 +8,31 @@ package org.fife.ui.autocomplete;
import java.util.EventObject; import java.util.EventObject;
/** /**
* An event fired by an instance of {@link AutoCompletion}. This can be * An event fired by an instance of {@link AutoCompletion}. This can be used by
* used by applications that wish to be notified of the auto-complete popup * applications that wish to be notified of the auto-complete popup window
* window showing and hiding. * showing and hiding.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public class AutoCompletionEvent extends EventObject { public class AutoCompletionEvent extends EventObject {
/** /**
* The type of this event. * The type of this event.
*/ */
private Type type; private Type type;
/** /**
* Constructor. * Constructor.
* *
* @param source * @param source The <code>AutoCompletion</code> instance that fired this event.
* The <code>AutoCompletion</code> instance that fired * @param type The event type.
* this event.
* @param type
* The event type.
*/ */
public AutoCompletionEvent(AutoCompletion source, Type type) { public AutoCompletionEvent(AutoCompletion source, Type type) {
super(source); super(source);
this.type = type; this.type = type;
} }
/** /**
* Returns the source <code>AutoCompletion</code> instance. This is just * Returns the source <code>AutoCompletion</code> instance. This is just
* shorthand for <code>return (AutoCompletion)getSource();</code>. * shorthand for <code>return (AutoCompletion)getSource();</code>.
@@ -45,7 +42,7 @@ public class AutoCompletionEvent extends EventObject {
public AutoCompletion getAutoCompletion() { public AutoCompletion getAutoCompletion() {
return (AutoCompletion) getSource(); return (AutoCompletion) getSource();
} }
/** /**
* Returns the type of this event. * Returns the type of this event.
* *
@@ -54,7 +51,7 @@ public class AutoCompletionEvent extends EventObject {
public Type getEventType() { public Type getEventType() {
return type; return type;
} }
/** /**
* Enumeration of the various types of this event. * Enumeration of the various types of this event.
*/ */
@@ -15,13 +15,12 @@ import java.util.EventListener;
* @version 1.0 * @version 1.0
*/ */
public interface AutoCompletionListener extends EventListener { public interface AutoCompletionListener extends EventListener {
/** /**
* Callback notified when a change to the <code>AutoCompletion</code>'s * Callback notified when a change to the <code>AutoCompletion</code>'s status
* status occurs. * occurs.
* *
* @param e * @param e The event.
* The event.
*/ */
void autoCompleteUpdate(AutoCompletionEvent e); void autoCompleteUpdate(AutoCompletionEvent e);
} }
@@ -15,32 +15,32 @@ import java.awt.Color;
* @version 1.0 * @version 1.0
*/ */
public class AutoCompletionStyleContext { public class AutoCompletionStyleContext {
/** /**
* The color used to denote the ending caret position for parameterized * The color used to denote the ending caret position for parameterized
* completions. * completions.
*/ */
private Color parameterizedCompletionCursorPositionColor; private Color parameterizedCompletionCursorPositionColor;
/** /**
* The color used to highlight copies of editable parameters in * The color used to highlight copies of editable parameters in parameterized
* parameterized completions. * completions.
*/ */
private Color parameterCopyColor; private Color parameterCopyColor;
/** /**
* The color of the outline highlight used to denote editable parameters * The color of the outline highlight used to denote editable parameters in
* in parameterized completions. * parameterized completions.
*/ */
private Color parameterOutlineColor; private Color parameterOutlineColor;
public AutoCompletionStyleContext() { public AutoCompletionStyleContext() {
setParameterOutlineColor(Color.gray); setParameterOutlineColor(Color.gray);
setParameterCopyColor(new Color(0xb4d7ff)); setParameterCopyColor(new Color(0xb4d7ff));
setParameterizedCompletionCursorPositionColor(new Color(0x00b400)); setParameterizedCompletionCursorPositionColor(new Color(0x00b400));
} }
/** /**
* Returns the color of the highlight painted on copies of editable * Returns the color of the highlight painted on copies of editable parameters
* parameters in parameterized completions. * in parameterized completions.
* *
* @return The color used. * @return The color used.
* @see #setParameterCopyColor(Color) * @see #setParameterCopyColor(Color)
@@ -48,10 +48,10 @@ public class AutoCompletionStyleContext {
public Color getParameterCopyColor() { public Color getParameterCopyColor() {
return parameterCopyColor; return parameterCopyColor;
} }
/** /**
* Returns the color used to denote the ending caret position for * Returns the color used to denote the ending caret position for parameterized
* parameterized completions. * completions.
* *
* @return The color used. * @return The color used.
* @see #setParameterizedCompletionCursorPositionColor(Color) * @see #setParameterizedCompletionCursorPositionColor(Color)
@@ -59,10 +59,10 @@ public class AutoCompletionStyleContext {
public Color getParameterizedCompletionCursorPositionColor() { public Color getParameterizedCompletionCursorPositionColor() {
return parameterizedCompletionCursorPositionColor; return parameterizedCompletionCursorPositionColor;
} }
/** /**
* Returns the color of the outline highlight used to denote editable * Returns the color of the outline highlight used to denote editable parameters
* parameters in parameterized completions. * in parameterized completions.
* *
* @return The color used. * @return The color used.
* @see #setParameterOutlineColor(Color) * @see #setParameterOutlineColor(Color)
@@ -70,37 +70,34 @@ public class AutoCompletionStyleContext {
public Color getParameterOutlineColor() { public Color getParameterOutlineColor() {
return parameterOutlineColor; return parameterOutlineColor;
} }
/** /**
* Sets the color of the highlight painted on copies of editable * Sets the color of the highlight painted on copies of editable parameters in
* parameters in parameterized completions. * parameterized completions.
* *
* @param color * @param color The color to use.
* The color to use.
* @see #setParameterCopyColor(Color) * @see #setParameterCopyColor(Color)
*/ */
public void setParameterCopyColor(Color color) { public void setParameterCopyColor(Color color) {
this.parameterCopyColor = color; this.parameterCopyColor = color;
} }
/** /**
* Sets the color used to denote the ending caret position for * Sets the color used to denote the ending caret position for parameterized
* parameterized completions. * completions.
* *
* @param color * @param color The color to use.
* The color to use.
* @see #getParameterizedCompletionCursorPositionColor() * @see #getParameterizedCompletionCursorPositionColor()
*/ */
public void setParameterizedCompletionCursorPositionColor(Color color) { public void setParameterizedCompletionCursorPositionColor(Color color) {
this.parameterizedCompletionCursorPositionColor = color; this.parameterizedCompletionCursorPositionColor = color;
} }
/** /**
* Sets the color of the outline highlight used to denote editable * Sets the color of the outline highlight used to denote editable parameters in
* parameters in parameterized completions. * parameterized completions.
* *
* @param color * @param color The color to use.
* The color to use.
* @see #getParameterOutlineColor() * @see #getParameterOutlineColor()
*/ */
public void setParameterOutlineColor(Color color) { public void setParameterOutlineColor(Color color) {
@@ -7,9 +7,9 @@
package org.fife.ui.autocomplete; package org.fife.ui.autocomplete;
/** /**
* A straightforward {@link Completion} implementation. This implementation * A straightforward {@link Completion} implementation. This implementation can
* can be used if you have a relatively short number of static completions * be used if you have a relatively short number of static completions with no
* with no (or short) summaries. * (or short) summaries.
* <p> * <p>
* *
* This implementation uses the replacement text as the input text. It also * This implementation uses the replacement text as the input text. It also
@@ -20,53 +20,44 @@ package org.fife.ui.autocomplete;
* @version 1.0 * @version 1.0
*/ */
public class BasicCompletion extends AbstractCompletion { public class BasicCompletion extends AbstractCompletion {
private String replacementText; private String replacementText;
private String shortDesc; private String shortDesc;
private String summary; private String summary;
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The parent completion provider.
* The parent completion provider. * @param replacementText The text to replace.
* @param replacementText
* The text to replace.
*/ */
public BasicCompletion(CompletionProvider provider, String replacementText) { public BasicCompletion(CompletionProvider provider, String replacementText) {
this(provider, replacementText, null); this(provider, replacementText, null);
} }
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The parent completion provider.
* The parent completion provider. * @param replacementText The text to replace.
* @param replacementText * @param shortDesc A short description of the completion. This will be
* The text to replace. * displayed in the completion list. This may be
* @param shortDesc * <code>null</code>.
* A short description of the completion. This will be
* displayed in the completion list. This may be
* <code>null</code>.
*/ */
public BasicCompletion(CompletionProvider provider, String replacementText, String shortDesc) { public BasicCompletion(CompletionProvider provider, String replacementText, String shortDesc) {
this(provider, replacementText, shortDesc, null); this(provider, replacementText, shortDesc, null);
} }
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The parent completion provider.
* The parent completion provider. * @param replacementText The text to replace.
* @param replacementText * @param shortDesc A short description of the completion. This will be
* The text to replace. * displayed in the completion list. This may be
* @param shortDesc * <code>null</code>.
* A short description of the completion. This will be * @param summary The summary of this completion. This should be HTML.
* displayed in the completion list. This may be * This may be <code>null</code>.
* <code>null</code>.
* @param summary
* The summary of this completion. This should be HTML.
* This may be <code>null</code>.
*/ */
public BasicCompletion(CompletionProvider provider, String replacementText, String shortDesc, String summary) { public BasicCompletion(CompletionProvider provider, String replacementText, String shortDesc, String summary) {
super(provider); super(provider);
@@ -74,7 +65,7 @@ public class BasicCompletion extends AbstractCompletion {
this.shortDesc = shortDesc; this.shortDesc = shortDesc;
this.summary = summary; this.summary = summary;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -82,10 +73,10 @@ public class BasicCompletion extends AbstractCompletion {
public String getReplacementText() { public String getReplacementText() {
return replacementText; return replacementText;
} }
/** /**
* Returns the short description of this completion, usually used in * Returns the short description of this completion, usually used in the
* the completion choices list. * completion choices list.
* *
* @return The short description, or <code>null</code> if there is none. * @return The short description, or <code>null</code> if there is none.
* @see #setShortDescription(String) * @see #setShortDescription(String)
@@ -93,7 +84,7 @@ public class BasicCompletion extends AbstractCompletion {
public String getShortDescription() { public String getShortDescription() {
return shortDesc; return shortDesc;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -101,32 +92,30 @@ public class BasicCompletion extends AbstractCompletion {
public String getSummary() { public String getSummary() {
return summary; return summary;
} }
/** /**
* Sets the short description of this completion. * Sets the short description of this completion.
* *
* @param shortDesc * @param shortDesc The short description of this completion.
* The short description of this completion.
* @see #getShortDescription() * @see #getShortDescription()
*/ */
public void setShortDescription(String shortDesc) { public void setShortDescription(String shortDesc) {
this.shortDesc = shortDesc; this.shortDesc = shortDesc;
} }
/** /**
* Sets the summary for this completion. * Sets the summary for this completion.
* *
* @param summary * @param summary The summary for this completion.
* The summary for this completion.
* @see #getSummary() * @see #getSummary()
*/ */
public void setSummary(String summary) { public void setSummary(String summary) {
this.summary = summary; this.summary = summary;
} }
/** /**
* Returns a string representation of this completion. If the short * Returns a string representation of this completion. If the short description
* description is not <code>null</code>, this method will return: * is not <code>null</code>, this method will return:
* *
* <code>getInputText() + " - " + shortDesc</code> * <code>getInputText() + " - " + shortDesc</code>
* *
+51 -59
View File
@@ -10,20 +10,20 @@ import javax.swing.Icon;
import javax.swing.text.JTextComponent; import javax.swing.text.JTextComponent;
/** /**
* Represents a completion choice. A {@link CompletionProvider} returns lists * Represents a completion choice. A {@link CompletionProvider} returns lists of
* of objects implementing this interface. A <tt>Completion</tt> contains the * objects implementing this interface. A <tt>Completion</tt> contains the
* following information: * following information:
* *
* <ul> * <ul>
* <li>The text the user must (begin to) input for this to be a completion * <li>The text the user must (begin to) input for this to be a completion
* choice. * choice.
* <li>The text that will be filled in if the user chooses this completion. * <li>The text that will be filled in if the user chooses this completion. Note
* Note that often, this is the same as the text the user must (begin to) * that often, this is the same as the text the user must (begin to) enter, but
* enter, but this doesn't have to be the case. * this doesn't have to be the case.
* <li>Summary HTML that describes this completion. This is information that * <li>Summary HTML that describes this completion. This is information that can
* can be displayed in a helper "tooltip"-style window beside the * be displayed in a helper "tooltip"-style window beside the completion list.
* completion list. This may be <code>null</code>. It may also be * This may be <code>null</code>. It may also be lazily generated to cut down on
* lazily generated to cut down on memory usage. * memory usage.
* <li>The <tt>CompletionProvider</tt> that returned this completion. * <li>The <tt>CompletionProvider</tt> that returned this completion.
* <li>Tool tip text that can be displayed when a mouse hovers over this * <li>Tool tip text that can be displayed when a mouse hovers over this
* completion in a text component. * completion in a text component.
@@ -34,112 +34,104 @@ import javax.swing.text.JTextComponent;
* @see AbstractCompletion * @see AbstractCompletion
*/ */
public interface Completion extends Comparable<Completion> { public interface Completion extends Comparable<Completion> {
/** /**
* Compares this completion to another one lexicographically, ignoring * Compares this completion to another one lexicographically, ignoring case.
* case.
* *
* @param other * @param other Another completion instance.
* Another completion instance.
* @return How this completion compares to the other one. * @return How this completion compares to the other one.
*/ */
@Override @Override
public int compareTo(Completion other); public int compareTo(Completion other);
/** /**
* Returns the portion of this completion that has already been entered * Returns the portion of this completion that has already been entered into the
* into the text component. The match is case-insensitive. * text component. The match is case-insensitive.
* <p> * <p>
* *
* This is a convenience method for: * This is a convenience method for:
* <code>getProvider().getAlreadyEnteredText(comp)</code>. * <code>getProvider().getAlreadyEnteredText(comp)</code>.
* *
* @param comp * @param comp The text component.
* The text component.
* @return The already-entered portion of this completion. * @return The already-entered portion of this completion.
*/ */
public String getAlreadyEntered(JTextComponent comp); public String getAlreadyEntered(JTextComponent comp);
/** /**
* Returns the icon to use for this completion. * Returns the icon to use for this completion.
* *
* @return The icon, or <code>null</code> for none. * @return The icon, or <code>null</code> for none.
*/ */
public Icon getIcon(); public Icon getIcon();
/** /**
* Returns the text that the user has to (start) typing for this completion * Returns the text that the user has to (start) typing for this completion to
* to be offered. Note that this will usually be the same value as * be offered. Note that this will usually be the same value as
* {@link #getReplacementText()}, but not always (a completion could be * {@link #getReplacementText()}, but not always (a completion could be a way to
* a way to implement shorthand, for example, "<code>sysout</code>" mapping * implement shorthand, for example, "<code>sysout</code>" mapping to
* to "<code>System.out.println(</code>"). * "<code>System.out.println(</code>").
* *
* @return The text the user has to (start) typing for this completion to * @return The text the user has to (start) typing for this completion to be
* be offered. * offered.
* @see #getReplacementText() * @see #getReplacementText()
*/ */
public String getInputText(); public String getInputText();
/** /**
* Returns the provider that returned this completion. * Returns the provider that returned this completion.
* *
* @return The provider. * @return The provider.
*/ */
public CompletionProvider getProvider(); public CompletionProvider getProvider();
/** /**
* Returns the "relevance" of this completion. This is used when sorting * Returns the "relevance" of this completion. This is used when sorting
* completions by their relevance. It is an abstract concept that may * completions by their relevance. It is an abstract concept that may mean
* mean different things to different languages, and may depend on the * different things to different languages, and may depend on the context of the
* context of the completion. * completion.
* <p> * <p>
* *
* By default, all completions have a relevance of <code>0</code>. The * By default, all completions have a relevance of <code>0</code>. The higher
* higher the value returned by this method, the higher up in the list * the value returned by this method, the higher up in the list this completion
* this completion will be; the lower the value returned, the lower it will * will be; the lower the value returned, the lower it will be.
* be. <code>Completion</code>s with equal relevance values will be * <code>Completion</code>s with equal relevance values will be sorted
* sorted alphabetically. * alphabetically.
* *
* @return The relevance of this completion. * @return The relevance of this completion.
*/ */
public int getRelevance(); public int getRelevance();
/** /**
* Returns the text to insert as the result of this auto-completion. This * Returns the text to insert as the result of this auto-completion. This is the
* is the "complete" text, including any text that replaces what the user * "complete" text, including any text that replaces what the user has already
* has already typed. * typed.
* *
* @return The replacement text. * @return The replacement text.
* @see #getInputText() * @see #getInputText()
*/ */
public String getReplacementText(); public String getReplacementText();
/** /**
* Returns the description of this auto-complete choice. This can be * Returns the description of this auto-complete choice. This can be used in a
* used in a popup "description window." * popup "description window."
* *
* @return This item's description. This should be HTML. It may be * @return This item's description. This should be HTML. It may be
* <code>null</code> if there is no description for this * <code>null</code> if there is no description for this completion.
* completion.
*/ */
public String getSummary(); public String getSummary();
/** /**
* Returns the tool tip text to display for mouse hovers over this * Returns the tool tip text to display for mouse hovers over this completion.
* completion.
* <p> * <p>
* *
* Note that for this functionality to be enabled, a * Note that for this functionality to be enabled, a <tt>JTextComponent</tt>
* <tt>JTextComponent</tt> must be registered with the * must be registered with the <tt>ToolTipManager</tt>, and the text component
* <tt>ToolTipManager</tt>, and the text component must know to search * must know to search for this value. In the case of an
* for this value. In the case of an * <a href="http://fifesoft.com/rsyntaxtextarea">RSyntaxTextArea</a>, this can
* <a href="http://fifesoft.com/rsyntaxtextarea">RSyntaxTextArea</a>, this * be done with a <tt>org.fife.ui.rtextarea.ToolTipSupplier</tt> that calls into
* can be done with a <tt>org.fife.ui.rtextarea.ToolTipSupplier</tt> that
* calls into
* {@link CompletionProvider#getCompletionsAt(JTextComponent, java.awt.Point)}. * {@link CompletionProvider#getCompletionsAt(JTextComponent, java.awt.Point)}.
* *
* @return The tool tip text for this completion, or <code>null</code> if * @return The tool tip text for this completion, or <code>null</code> if none.
* none.
*/ */
public String getToolTipText(); public String getToolTipText();
} }
@@ -26,8 +26,8 @@ import javax.swing.text.View;
/** /**
* A cell renderer that adds some pizazz when rendering the standard * A cell renderer that adds some pizazz when rendering the standard
* {@link Completion} types, like Eclipse and NetBeans do. Specifically, * {@link Completion} types, like Eclipse and NetBeans do. Specifically, this
* this renderer handles: * renderer handles:
* *
* <ul> * <ul>
* <li>{@link FunctionCompletion}s</li> * <li>{@link FunctionCompletion}s</li>
@@ -41,20 +41,20 @@ import javax.swing.text.View;
* @version 1.0 * @version 1.0
*/ */
public class CompletionCellRenderer extends DefaultListCellRenderer { public class CompletionCellRenderer extends DefaultListCellRenderer {
/** /**
* The alternating background color, or <code>null</code> if alternating * The alternating background color, or <code>null</code> if alternating row
* row colors should not be used. * colors should not be used.
*/ */
private static Color altBG; private static Color altBG;
/** /**
* The font to use when rendering items, or <code>null</code> if the * The font to use when rendering items, or <code>null</code> if the list's
* list's default font should be used. * default font should be used.
*/ */
private Font font; private Font font;
/** /**
* Whether to display the types of fields and return types of functions * Whether to display the types of fields and return types of functions in the
* in the completion text. * completion text.
*/ */
private boolean showTypes; private boolean showTypes;
/** /**
@@ -92,33 +92,32 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
* words. * words.
*/ */
private static final String PREFIX = "<html><nobr>"; private static final String PREFIX = "<html><nobr>";
/** /**
* Constructor. * Constructor.
*/ */
public CompletionCellRenderer() { public CompletionCellRenderer() {
init(); init();
} }
/** /**
* Constructor. This is primarily a hook for Substance, or any other * Constructor. This is primarily a hook for Substance, or any other Look and
* Look and Feel whose renderers look drastically different than standard * Feel whose renderers look drastically different than standard
* <code>DefaultListCellRenderer</code>s. Everything except for the text * <code>DefaultListCellRenderer</code>s. Everything except for the text
* rendering will be done by the delegate. In almost all scenarios, you * rendering will be done by the delegate. In almost all scenarios, you will
* will want to use the no-argument constructor instead of this one. * want to use the no-argument constructor instead of this one.
* *
* @param delegate * @param delegate The delegate renderer.
* The delegate renderer.
* @see #delegateToSubstanceRenderer() * @see #delegateToSubstanceRenderer()
*/ */
public CompletionCellRenderer(DefaultListCellRenderer delegate) { public CompletionCellRenderer(DefaultListCellRenderer delegate) {
setDelegateRenderer(delegate); setDelegateRenderer(delegate);
init(); init();
} }
/** /**
* Creates the icon to use if no icon is found for a specific completion. * Creates the icon to use if no icon is found for a specific completion. The
* The default implementation returns a 16x16 empty icon. * default implementation returns a 16x16 empty icon.
* *
* @return The icon. * @return The icon.
* @see #getEmptyIcon() * @see #getEmptyIcon()
@@ -126,34 +125,32 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
protected Icon createEmptyIcon() { protected Icon createEmptyIcon() {
return new EmptyIcon(16); return new EmptyIcon(16);
} }
/** /**
* Returns a decent "parameter" color based on the current default * Returns a decent "parameter" color based on the current default foreground
* foreground color. * color.
* *
* @return The parameter color to use. * @return The parameter color to use.
*/ */
private String createParamColor() { private String createParamColor() {
return Util.isLightForeground(getForeground()) ? Util.getHexString(Util.getHyperlinkForeground()) : "#aa0077"; return Util.isLightForeground(getForeground()) ? Util.getHexString(Util.getHyperlinkForeground()) : "#aa0077";
} }
/** /**
* Returns a decent "type" color based on the current default foreground * Returns a decent "type" color based on the current default foreground color.
* color.
* *
* @return The type color to use. * @return The type color to use.
*/ */
private String createTypeColor() { private String createTypeColor() {
return "#808080"; return "#808080";
} }
/** /**
* Attempts to delegate rendering to a Substance cell renderer. This * Attempts to delegate rendering to a Substance cell renderer. This should only
* should only be called if Substance is known to be on the classpath. * be called if Substance is known to be on the classpath.
* *
* @throws Exception * @throws Exception If Substance is not on the classpath, or some other error
* If Substance is not on the classpath, or some other * occurs creating the Substance cell renderer.
* error occurs creating the Substance cell renderer.
* @see Util#getUseSubstanceRenderers() * @see Util#getUseSubstanceRenderers()
* @see #setDelegateRenderer(DefaultListCellRenderer) * @see #setDelegateRenderer(DefaultListCellRenderer)
*/ */
@@ -162,7 +159,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
DefaultListCellRenderer delegate = (DefaultListCellRenderer) clazz.newInstance(); DefaultListCellRenderer delegate = (DefaultListCellRenderer) clazz.newInstance();
setDelegateRenderer(delegate); setDelegateRenderer(delegate);
} }
/** /**
* Returns the background color to use on alternating lines. * Returns the background color to use on alternating lines.
* *
@@ -173,7 +170,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
public static Color getAlternateBackground() { public static Color getAlternateBackground() {
return altBG; return altBG;
} }
/** /**
* Returns the delegate renderer, or <code>null</code> if there is none. * Returns the delegate renderer, or <code>null</code> if there is none.
* *
@@ -183,21 +180,21 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
public DefaultListCellRenderer getDelegateRenderer() { public DefaultListCellRenderer getDelegateRenderer() {
return delegate; return delegate;
} }
/** /**
* Returns the font used when rendering completions. * Returns the font used when rendering completions.
* *
* @return The font. If this is <code>null</code>, then the default list * @return The font. If this is <code>null</code>, then the default list font is
* font is used. * used.
* @see #setDisplayFont(Font) * @see #setDisplayFont(Font)
*/ */
public Font getDisplayFont() { public Font getDisplayFont() {
return font; return font;
} }
/** /**
* Returns the icon to use if no icon is found for a specific completion. * Returns the icon to use if no icon is found for a specific completion. This
* This icon is lazily created if necessary. * icon is lazily created if necessary.
* *
* @return The icon. * @return The icon.
* @see #createEmptyIcon() * @see #createEmptyIcon()
@@ -208,13 +205,12 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
} }
return emptyIcon; return emptyIcon;
} }
/** /**
* Returns an icon. * Returns an icon.
* *
* @param resource * @param resource The icon to retrieve. This should either be a file, or a
* The icon to retrieve. This should either be a file, * resource loadable by the current ClassLoader.
* or a resource loadable by the current ClassLoader.
* @return The icon. * @return The icon.
*/ */
protected Icon getIcon(String resource) { protected Icon getIcon(String resource) {
@@ -229,23 +225,19 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
} }
return url != null ? new ImageIcon(url) : null; return url != null ? new ImageIcon(url) : null;
} }
/** /**
* Returns the renderer. * Returns the renderer.
* *
* @param list * @param list The list of choices being rendered.
* The list of choices being rendered. * @param value The {@link Completion} being rendered.
* @param value * @param index The index into <code>list</code> being rendered.
* The {@link Completion} being rendered. * @param selected Whether the item is selected.
* @param index * @param hasFocus Whether the item has focus.
* The index into <code>list</code> being rendered.
* @param selected
* Whether the item is selected.
* @param hasFocus
* Whether the item has focus.
*/ */
@Override @Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected, boolean hasFocus) { public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected,
boolean hasFocus) {
super.getListCellRendererComponent(list, value, index, selected, hasFocus); super.getListCellRendererComponent(list, value, index, selected, hasFocus);
if (font != null) { if (font != null) {
setFont(font); // Overrides super's setFont(list.getFont()). setFont(font); // Overrides super's setFont(list.getFont()).
@@ -282,10 +274,10 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
} }
return this; return this;
} }
/** /**
* Returns whether the types of fields and return types of methods are * Returns whether the types of fields and return types of methods are shown in
* shown in the completion text. * the completion text.
* *
* @return Whether to show the types. * @return Whether to show the types.
* @see #setShowTypes(boolean) * @see #setShowTypes(boolean)
@@ -293,7 +285,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
public boolean getShowTypes() { public boolean getShowTypes() {
return showTypes; return showTypes;
} }
private void init() { private void init() {
// setDisplayFont(new Font("Monospaced", Font.PLAIN, 12)); // setDisplayFont(new Font("Monospaced", Font.PLAIN, 12));
setShowTypes(true); setShowTypes(true);
@@ -301,7 +293,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
paramColor = createParamColor(); paramColor = createParamColor();
paintTextR = new Rectangle(); paintTextR = new Rectangle();
} }
@Override @Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
// super.paintComponent(g); // super.paintComponent(g);
@@ -342,22 +334,18 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
} }
} }
} }
/** /**
* Prepares this renderer to display a function completion. * Prepares this renderer to display a function completion.
* *
* @param list * @param list The list of choices being rendered.
* The list of choices being rendered. * @param fc The completion to render.
* @param fc * @param index The index into <code>list</code> being rendered.
* The completion to render. * @param selected Whether the item is selected.
* @param index * @param hasFocus Whether the item has focus.
* The index into <code>list</code> being rendered.
* @param selected
* Whether the item is selected.
* @param hasFocus
* Whether the item has focus.
*/ */
protected void prepareForFunctionCompletion(JList list, FunctionCompletion fc, int index, boolean selected, boolean hasFocus) { protected void prepareForFunctionCompletion(JList list, FunctionCompletion fc, int index, boolean selected,
boolean hasFocus) {
StringBuilder sb = new StringBuilder(PREFIX); StringBuilder sb = new StringBuilder(PREFIX);
sb.append(fc.getName()); sb.append(fc.getName());
char paramListStart = fc.getProvider().getParameterListStart(); char paramListStart = fc.getProvider().getParameterListStart();
@@ -404,41 +392,32 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
} }
setText(sb.toString()); setText(sb.toString());
} }
/** /**
* Prepares this renderer to display a markup tag completion. * Prepares this renderer to display a markup tag completion.
* *
* @param list * @param list The list of choices being rendered.
* The list of choices being rendered. * @param mc The completion to render.
* @param mc * @param index The index into <code>list</code> being rendered.
* The completion to render. * @param selected Whether the item is selected.
* @param index * @param hasFocus Whether the item has focus.
* The index into <code>list</code> being rendered.
* @param selected
* Whether the item is selected.
* @param hasFocus
* Whether the item has focus.
*/ */
protected void prepareForMarkupTagCompletion(JList list, MarkupTagCompletion mc, int index, boolean selected, boolean hasFocus) { protected void prepareForMarkupTagCompletion(JList list, MarkupTagCompletion mc, int index, boolean selected,
boolean hasFocus) {
StringBuilder sb = new StringBuilder(PREFIX); StringBuilder sb = new StringBuilder(PREFIX);
sb.append(mc.getName()); sb.append(mc.getName());
setText(sb.toString()); setText(sb.toString());
} }
/** /**
* Prepares this renderer to display a completion not specifically handled * Prepares this renderer to display a completion not specifically handled
* elsewhere. * elsewhere.
* *
* @param list * @param list The list of choices being rendered.
* The list of choices being rendered. * @param c The completion to render.
* @param c * @param index The index into <code>list</code> being rendered.
* The completion to render. * @param selected Whether the item is selected.
* @param index * @param hasFocus Whether the item has focus.
* The index into <code>list</code> being rendered.
* @param selected
* Whether the item is selected.
* @param hasFocus
* Whether the item has focus.
*/ */
protected void prepareForOtherCompletion(JList list, Completion c, int index, boolean selected, boolean hasFocus) { protected void prepareForOtherCompletion(JList list, Completion c, int index, boolean selected, boolean hasFocus) {
StringBuilder sb = new StringBuilder(PREFIX); StringBuilder sb = new StringBuilder(PREFIX);
@@ -458,22 +437,18 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
} }
setText(sb.toString()); setText(sb.toString());
} }
/** /**
* Prepares this renderer to display a template completion. * Prepares this renderer to display a template completion.
* *
* @param list * @param list The list of choices being rendered.
* The list of choices being rendered. * @param tc The completion to render.
* @param tc * @param index The index into <code>list</code> being rendered.
* The completion to render. * @param selected Whether the item is selected.
* @param index * @param hasFocus Whether the item has focus.
* The index into <code>list</code> being rendered.
* @param selected
* Whether the item is selected.
* @param hasFocus
* Whether the item has focus.
*/ */
protected void prepareForTemplateCompletion(JList list, TemplateCompletion tc, int index, boolean selected, boolean hasFocus) { protected void prepareForTemplateCompletion(JList list, TemplateCompletion tc, int index, boolean selected,
boolean hasFocus) {
StringBuilder sb = new StringBuilder(PREFIX); StringBuilder sb = new StringBuilder(PREFIX);
sb.append(tc.getInputText()); sb.append(tc.getInputText());
String definition = tc.getShortDescription(); String definition = tc.getShortDescription();
@@ -489,22 +464,18 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
} }
setText(sb.toString()); setText(sb.toString());
} }
/** /**
* Prepares this renderer to display a variable completion. * Prepares this renderer to display a variable completion.
* *
* @param list * @param list The list of choices being rendered.
* The list of choices being rendered. * @param vc The completion to render.
* @param vc * @param index The index into <code>list</code> being rendered.
* The completion to render. * @param selected Whether the item is selected.
* @param index * @param hasFocus Whether the item has focus.
* The index into <code>list</code> being rendered.
* @param selected
* Whether the item is selected.
* @param hasFocus
* Whether the item has focus.
*/ */
protected void prepareForVariableCompletion(JList list, VariableCompletion vc, int index, boolean selected, boolean hasFocus) { protected void prepareForVariableCompletion(JList list, VariableCompletion vc, int index, boolean selected,
boolean hasFocus) {
StringBuilder sb = new StringBuilder(PREFIX); StringBuilder sb = new StringBuilder(PREFIX);
sb.append(vc.getName()); sb.append(vc.getName());
if (getShowTypes() && vc.getType() != null) { if (getShowTypes() && vc.getType() != null) {
@@ -519,81 +490,73 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
} }
setText(sb.toString()); setText(sb.toString());
} }
/** /**
* Sets the background color to use on alternating lines. * Sets the background color to use on alternating lines.
* *
* @param altBG * @param altBG The new alternate background color. If this is
* The new alternate background color. If this is * <code>null</code>, alternating lines will not use different
* <code>null</code>, alternating lines will not use different * background colors.
* background colors.
* @see #getAlternateBackground() * @see #getAlternateBackground()
*/ */
public static void setAlternateBackground(Color altBG) { public static void setAlternateBackground(Color altBG) {
CompletionCellRenderer.altBG = altBG; CompletionCellRenderer.altBG = altBG;
} }
/** /**
* Sets the delegate renderer. Most users will never use this method; it * Sets the delegate renderer. Most users will never use this method; it is
* is primarily a hook for Substance and other Look and Feels whose * primarily a hook for Substance and other Look and Feels whose renderers look
* renderers look drastically different from the standard * drastically different from the standard <code>DefaultListCellRenderer</code>.
* <code>DefaultListCellRenderer</code>.
* *
* @param delegate * @param delegate The new delegate renderer. If this is <code>null</code>, the
* The new delegate renderer. If this is <code>null</code>, * default rendering of this component is used.
* the default rendering of this component is used.
* @see #getDelegateRenderer() * @see #getDelegateRenderer()
* @see #delegateToSubstanceRenderer() * @see #delegateToSubstanceRenderer()
*/ */
public void setDelegateRenderer(DefaultListCellRenderer delegate) { public void setDelegateRenderer(DefaultListCellRenderer delegate) {
this.delegate = delegate; this.delegate = delegate;
} }
/** /**
* Sets the font to use when rendering completion items. * Sets the font to use when rendering completion items.
* *
* @param font * @param font The font to use. If this is <code>null</code>, then the default
* The font to use. If this is <code>null</code>, then * list font is used.
* the default list font is used.
* @see #getDisplayFont() * @see #getDisplayFont()
*/ */
public void setDisplayFont(Font font) { public void setDisplayFont(Font font) {
this.font = font; this.font = font;
} }
/** /**
* Sets the icon to display based off of a completion, falling back to the * Sets the icon to display based off of a completion, falling back to the empty
* empty icon if the completion has no icon. * icon if the completion has no icon.
* *
* @param completion * @param completion The completion to check.
* The completion to check.
* @see #setIconWithDefault(Completion, Icon) * @see #setIconWithDefault(Completion, Icon)
*/ */
protected void setIconWithDefault(Completion completion) { protected void setIconWithDefault(Completion completion) {
setIconWithDefault(completion, getEmptyIcon()); setIconWithDefault(completion, getEmptyIcon());
} }
/** /**
* Sets the icon to display based off of a completion, falling back to a * Sets the icon to display based off of a completion, falling back to a default
* default icon if the completion has no icon. * icon if the completion has no icon.
* *
* @param completion * @param completion The completion to check.
* The completion to check. * @param defaultIcon The icon to use if <code>completion</code> does not
* @param defaultIcon * specify an icon.
* The icon to use if <code>completion</code> does not
* specify an icon.
* @see #setIconWithDefault(Completion) * @see #setIconWithDefault(Completion)
*/ */
protected void setIconWithDefault(Completion completion, Icon defaultIcon) { protected void setIconWithDefault(Completion completion, Icon defaultIcon) {
Icon icon = completion.getIcon(); Icon icon = completion.getIcon();
setIcon(icon != null ? icon : (defaultIcon != null ? defaultIcon : emptyIcon)); setIcon(icon != null ? icon : (defaultIcon != null ? defaultIcon : emptyIcon));
} }
/** /**
* Sets the color to use for function arguments. * Sets the color to use for function arguments.
* *
* @param color * @param color The color to use. This is ignored if <code>null</code>.
* The color to use. This is ignored if <code>null</code>.
* @see #setTypeColor(Color) * @see #setTypeColor(Color)
*/ */
public void setParamColor(Color color) { public void setParamColor(Color color) {
@@ -601,27 +564,25 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
paramColor = Util.getHexString(color); paramColor = Util.getHexString(color);
} }
} }
/** /**
* Sets whether the types of fields and return types of methods are * Sets whether the types of fields and return types of methods are shown in the
* shown in the completion text. * completion text.
* *
* @param show * @param show Whether to show the types.
* Whether to show the types.
* @see #getShowTypes() * @see #getShowTypes()
*/ */
public void setShowTypes(boolean show) { public void setShowTypes(boolean show) {
this.showTypes = show; this.showTypes = show;
} }
/** /**
* Sets the color to use for function/field types. Note that if * Sets the color to use for function/field types. Note that if
* {@link #getShowTypes()} returns <code>false</code>, this property * {@link #getShowTypes()} returns <code>false</code>, this property effectively
* effectively does nothing. * does nothing.
* *
* @param color * @param color The color to use for types. This is ignored if
* The color to use for types. This is ignored if * <code>null</code>.
* <code>null</code>.
* @see #setShowTypes(boolean) * @see #setShowTypes(boolean)
* @see #setParamColor(Color) * @see #setParamColor(Color)
*/ */
@@ -630,7 +591,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
typeColor = Util.getHexString(color); typeColor = Util.getHexString(color);
} }
} }
/** /**
* Overridden to update our delegate, if necessary. * Overridden to update our delegate, if necessary.
*/ */
@@ -13,30 +13,29 @@ import java.util.List;
import javax.swing.AbstractListModel; import javax.swing.AbstractListModel;
/** /**
* A list model implementation that allows the bulk addition of elements. * A list model implementation that allows the bulk addition of elements. This
* This is the only feature missing from <code>DefaultListModel</code> that * is the only feature missing from <code>DefaultListModel</code> that we need.
* we need.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
class CompletionListModel extends AbstractListModel { class CompletionListModel extends AbstractListModel {
/** /**
* Container for items in this model. * Container for items in this model.
*/ */
private List<Completion> delegate; private List<Completion> delegate;
/** /**
* Constructor. * Constructor.
*/ */
public CompletionListModel() { public CompletionListModel() {
delegate = new ArrayList<Completion>(); delegate = new ArrayList<Completion>();
} }
/** /**
* Removes all of the elements from this list. The list will * Removes all of the elements from this list. The list will be empty after this
* be empty after this call returns (unless it throws an exception). * call returns (unless it throws an exception).
* *
* @see #setContents(Collection) * @see #setContents(Collection)
*/ */
@@ -47,7 +46,7 @@ class CompletionListModel extends AbstractListModel {
fireIntervalRemoved(this, 0, end); fireIntervalRemoved(this, 0, end);
} }
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -55,7 +54,7 @@ class CompletionListModel extends AbstractListModel {
public Object getElementAt(int index) { public Object getElementAt(int index) {
return delegate.get(index); return delegate.get(index);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -63,12 +62,11 @@ class CompletionListModel extends AbstractListModel {
public int getSize() { public int getSize() {
return delegate.size(); return delegate.size();
} }
/** /**
* Sets the contents of this model. All previous contents are removed. * Sets the contents of this model. All previous contents are removed.
* *
* @param contents * @param contents The new contents of this model.
* The new contents of this model.
*/ */
public void setContents(Collection<Completion> contents) { public void setContents(Collection<Completion> contents) {
clear(); clear();
@@ -25,7 +25,7 @@ import javax.swing.text.JTextComponent;
* @version 1.0 * @version 1.0
*/ */
public interface CompletionProvider { public interface CompletionProvider {
/** /**
* Clears the values used to identify and insert "parameterized completions" * Clears the values used to identify and insert "parameterized completions"
* (e.g. functions or methods). After this method is called, functions and * (e.g. functions or methods). After this method is called, functions and
@@ -34,111 +34,103 @@ public interface CompletionProvider {
* @see #setParameterizedCompletionParams(char, String, char) * @see #setParameterizedCompletionParams(char, String, char)
*/ */
public void clearParameterizedCompletionParams(); public void clearParameterizedCompletionParams();
/** /**
* Returns the text just before the current caret position that could be * Returns the text just before the current caret position that could be the
* the start of something auto-completable. * start of something auto-completable.
* *
* @param comp * @param comp The text component.
* The text component. * @return The text. A return value of <code>null</code> means nothing should be
* @return The text. A return value of <code>null</code> means nothing * auto-completed; a value of an empty string (<code>""</code>) means
* should be auto-completed; a value of an empty string * auto-completion should still be considered (i.e., all possible
* (<code>""</code>) means auto-completion should still be * choices are valid).
* considered (i.e., all possible choices are valid).
*/ */
public String getAlreadyEnteredText(JTextComponent comp); public String getAlreadyEnteredText(JTextComponent comp);
/** /**
* Gets the possible completions for the text component at the current * Gets the possible completions for the text component at the current caret
* caret position. * position.
* *
* @param comp * @param comp The text component.
* The text component. * @return The list of {@link Completion}s. If no completions are available,
* @return The list of {@link Completion}s. If no completions are * this method should return an empty list.
* available, this method should return an empty list.
*/ */
public List<Completion> getCompletions(JTextComponent comp); public List<Completion> getCompletions(JTextComponent comp);
/** /**
* Returns the completions that have been entered at the specified visual * Returns the completions that have been entered at the specified visual
* location. This can be used for tool tips when the user hovers the * location. This can be used for tool tips when the user hovers the mouse over
* mouse over completed text. * completed text.
* *
* @param comp * @param comp The text component.
* The text component. * @param p The position, usually from a <tt>MouseEvent</tt>.
* @param p
* The position, usually from a <tt>MouseEvent</tt>.
* @return The completions, or an empty list if there are none. * @return The completions, or an empty list if there are none.
*/ */
public List<Completion> getCompletionsAt(JTextComponent comp, Point p); public List<Completion> getCompletionsAt(JTextComponent comp, Point p);
/** /**
* Returns the cell renderer for completions returned from this provider. * Returns the cell renderer for completions returned from this provider.
* *
* @return The cell renderer, or <code>null</code> if the default should * @return The cell renderer, or <code>null</code> if the default should be
* be used. * used.
* @see #setListCellRenderer(ListCellRenderer) * @see #setListCellRenderer(ListCellRenderer)
*/ */
public ListCellRenderer getListCellRenderer(); public ListCellRenderer getListCellRenderer();
/** /**
* Returns an object that can return a list of completion choices for * Returns an object that can return a list of completion choices for
* parameters. This is used when a user code-completes a parameterized * parameters. This is used when a user code-completes a parameterized
* completion, such as a function or method. For any parameter to the * completion, such as a function or method. For any parameter to the
* function/method, this object can return possible completions. * function/method, this object can return possible completions.
* *
* @return The parameter choices provider, or <code>null</code> if * @return The parameter choices provider, or <code>null</code> if none is
* none is installed. * installed.
*/ */
public ParameterChoicesProvider getParameterChoicesProvider(); public ParameterChoicesProvider getParameterChoicesProvider();
/** /**
* Returns a list of parameterized completions that have been entered * Returns a list of parameterized completions that have been entered at the
* at the current caret position of a text component (and thus can have * current caret position of a text component (and thus can have their
* their completion choices displayed). * completion choices displayed).
* *
* @param tc * @param tc The text component.
* The text component. * @return The list of {@link ParameterizedCompletion}s. If no completions are
* @return The list of {@link ParameterizedCompletion}s. If no completions * available, this may be <code>null</code>.
* are available, this may be <code>null</code>.
*/ */
public List<ParameterizedCompletion> getParameterizedCompletions(JTextComponent tc); public List<ParameterizedCompletion> getParameterizedCompletions(JTextComponent tc);
/** /**
* Returns the text that marks the end of a list of parameters to a * Returns the text that marks the end of a list of parameters to a function or
* function or method. * method.
* *
* @return The text for a parameter list end, for example, * @return The text for a parameter list end, for example, '<code>)</code>'.
* '<code>)</code>'.
* @see #getParameterListStart() * @see #getParameterListStart()
* @see #getParameterListSeparator() * @see #getParameterListSeparator()
* @see #setParameterizedCompletionParams(char, String, char) * @see #setParameterizedCompletionParams(char, String, char)
*/ */
public char getParameterListEnd(); public char getParameterListEnd();
/** /**
* Returns the text that separates parameters to a function or method. * Returns the text that separates parameters to a function or method.
* *
* @return The text that separates parameters, for example, * @return The text that separates parameters, for example, "<code>, </code>".
* "<code>, </code>".
* @see #getParameterListStart() * @see #getParameterListStart()
* @see #getParameterListEnd() * @see #getParameterListEnd()
* @see #setParameterizedCompletionParams(char, String, char) * @see #setParameterizedCompletionParams(char, String, char)
*/ */
public String getParameterListSeparator(); public String getParameterListSeparator();
/** /**
* Returns the text that marks the start of a list of parameters to a * Returns the text that marks the start of a list of parameters to a function
* function or method. * or method.
* *
* @return The text for a parameter list start, for example, * @return The text for a parameter list start, for example, "<code>(</code>".
* "<code>(</code>".
* @see #getParameterListEnd() * @see #getParameterListEnd()
* @see #getParameterListSeparator() * @see #getParameterListSeparator()
* @see #setParameterizedCompletionParams(char, String, char) * @see #setParameterizedCompletionParams(char, String, char)
*/ */
public char getParameterListStart(); public char getParameterListStart();
/** /**
* Returns the parent completion provider. * Returns the parent completion provider.
* *
@@ -146,59 +138,53 @@ public interface CompletionProvider {
* @see #setParent(CompletionProvider) * @see #setParent(CompletionProvider)
*/ */
public CompletionProvider getParent(); public CompletionProvider getParent();
/** /**
* This method is called if auto-activation is enabled in the parent * This method is called if auto-activation is enabled in the parent
* {@link AutoCompletion} after the user types a single character. This * {@link AutoCompletion} after the user types a single character. This provider
* provider should check the text at the current caret position of the * should check the text at the current caret position of the text component,
* text component, and decide whether auto-activation would be appropriate * and decide whether auto-activation would be appropriate here. For example, a
* here. For example, a <code>CompletionProvider</code> for Java might * <code>CompletionProvider</code> for Java might want to return
* want to return <code>true</code> for this method only if the last * <code>true</code> for this method only if the last character typed was a
* character typed was a '<code>.</code>'. * '<code>.</code>'.
* *
* @param tc * @param tc The text component.
* The text component.
* @return Whether auto-activation would be appropriate. * @return Whether auto-activation would be appropriate.
*/ */
public boolean isAutoActivateOkay(JTextComponent tc); public boolean isAutoActivateOkay(JTextComponent tc);
/** /**
* Sets the renderer to use when displaying completion choices. * Sets the renderer to use when displaying completion choices.
* *
* @param r * @param r The renderer to use.
* The renderer to use.
* @see #getListCellRenderer() * @see #getListCellRenderer()
*/ */
public void setListCellRenderer(ListCellRenderer r); public void setListCellRenderer(ListCellRenderer r);
/** /**
* Sets the values used to identify and insert "parameterized completions" * Sets the values used to identify and insert "parameterized completions" (e.g.
* (e.g. functions or methods). If this method isn't called, functions * functions or methods). If this method isn't called, functions and methods
* and methods will not have their parameters auto-completed. * will not have their parameters auto-completed.
* *
* @param listStart * @param listStart The character that marks the beginning of a list of
* The character that marks the beginning of a list of * parameters, such as '<tt>(</tt>' in C or Java.
* parameters, such as '<tt>(</tt>' in C or Java. * @param separator Text that should separate parameters in a parameter list
* @param separator * when one is inserted. For example, "<tt>, </tt>".
* Text that should separate parameters in a parameter * @param listEnd The character that marks the end of a list of parameters,
* list when one is inserted. For example, "<tt>, </tt>". * such as '<tt>)</tt>' in C or Java.
* @param listEnd * @throws IllegalArgumentException If either <tt>listStart</tt> or
* The character that marks the end of a list of parameters, * <tt>listEnd</tt> is not printable ASCII, or
* such as '<tt>)</tt>' in C or Java. * if <tt>separator</tt> is <code>null</code>
* @throws IllegalArgumentException * or an empty string.
* If either <tt>listStart</tt> or
* <tt>listEnd</tt> is not printable ASCII, or if
* <tt>separator</tt> is <code>null</code> or an empty string.
* @see #clearParameterizedCompletionParams() * @see #clearParameterizedCompletionParams()
*/ */
public void setParameterizedCompletionParams(char listStart, String separator, char listEnd); public void setParameterizedCompletionParams(char listStart, String separator, char listEnd);
/** /**
* Sets the parent completion provider. * Sets the parent completion provider.
* *
* @param parent * @param parent The parent provider. <code>null</code> means there will be no
* The parent provider. <code>null</code> means there will * parent provider.
* be no parent provider.
* @see #getParent() * @see #getParent()
*/ */
public void setParent(CompletionProvider parent); public void setParent(CompletionProvider parent);
@@ -182,7 +182,8 @@ public abstract class CompletionProviderBase implements CompletionProvider {
} catch (BadLocationException ble) { // Never happens } catch (BadLocationException ble) { // Never happens
ble.printStackTrace(); ble.printStackTrace();
} }
return (autoActivateAfterLetters && Character.isLetter(ch)) || (autoActivateChars != null && autoActivateChars.indexOf(ch) > -1); return (autoActivateAfterLetters && Character.isLetter(ch))
|| (autoActivateChars != null && autoActivateChars.indexOf(ch) > -1);
} }
/** /**
@@ -18,15 +18,15 @@ import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.DefaultHandler;
/** /**
* Parser for an XML file describing a procedural language such as C. XML * Parser for an XML file describing a procedural language such as C. XML files
* files will be validated against the <code>CompletionXml.dtd</code> DTD * will be validated against the <code>CompletionXml.dtd</code> DTD found in
* found in this package. * this package.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public class CompletionXMLParser extends DefaultHandler { public class CompletionXMLParser extends DefaultHandler {
/** /**
* The completions found after parsing the XML. * The completions found after parsing the XML.
*/ */
@@ -68,36 +68,31 @@ public class CompletionXMLParser extends DefaultHandler {
*/ */
private String funcCompletionType; private String funcCompletionType;
/** /**
* The class loader to use to load custom completion classes, such as * The class loader to use to load custom completion classes, such as the one
* the one defined by {@link #funcCompletionType}. If this is * defined by {@link #funcCompletionType}. If this is <code>null</code>, then a
* <code>null</code>, then a default class loader is used. This field * default class loader is used. This field will usually be <code>null</code>.
* will usually be <code>null</code>.
*/ */
private static ClassLoader DEFAULT_COMPLETION_CLASS_LOADER; private static ClassLoader DEFAULT_COMPLETION_CLASS_LOADER;
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The provider to get completions for.
* The provider to get completions for.
* @see #reset(CompletionProvider) * @see #reset(CompletionProvider)
*/ */
public CompletionXMLParser(CompletionProvider provider) { public CompletionXMLParser(CompletionProvider provider) {
this(provider, null); this(provider, null);
} }
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The provider to get completions for.
* The provider to get completions for. * @param cl The class loader to use, if necessary, when loading classes
* @param cl * from the XML (custom {@link FunctionCompletion}s, for
* The class loader to use, if necessary, when loading classes * example). This may be <code>null</code> if the default is to
* from the XML (custom {@link FunctionCompletion}s, for * be used, or if the XML does not define specific classes for
* example). * completion types.
* This may be <code>null</code> if the default is to be used, or
* if the XML does not define specific classes for completion
* types.
* @see #reset(CompletionProvider) * @see #reset(CompletionProvider)
*/ */
public CompletionXMLParser(CompletionProvider provider, ClassLoader cl) { public CompletionXMLParser(CompletionProvider provider, ClassLoader cl) {
@@ -115,7 +110,7 @@ public class CompletionXMLParser extends DefaultHandler {
paramStartChar = paramEndChar = 0; paramStartChar = paramEndChar = 0;
paramSeparator = null; paramSeparator = null;
} }
/** /**
* Called when character data inside an element is found. * Called when character data inside an element is found.
*/ */
@@ -129,7 +124,7 @@ public class CompletionXMLParser extends DefaultHandler {
returnValDesc.append(ch, start, length); returnValDesc.append(ch, start, length);
} }
} }
private FunctionCompletion createFunctionCompletion() { private FunctionCompletion createFunctionCompletion() {
FunctionCompletion fc = null; FunctionCompletion fc = null;
if (funcCompletionType != null) { if (funcCompletionType != null) {
@@ -163,7 +158,7 @@ public class CompletionXMLParser extends DefaultHandler {
} }
return fc; return fc;
} }
private BasicCompletion createOtherCompletion() { private BasicCompletion createOtherCompletion() {
BasicCompletion bc = new BasicCompletion(provider, name); BasicCompletion bc = new BasicCompletion(provider, name);
if (desc.length() > 0) { if (desc.length() > 0) {
@@ -172,7 +167,7 @@ public class CompletionXMLParser extends DefaultHandler {
} }
return bc; return bc;
} }
private MarkupTagCompletion createMarkupTagCompletion() { private MarkupTagCompletion createMarkupTagCompletion() {
MarkupTagCompletion mc = new MarkupTagCompletion(provider, name); MarkupTagCompletion mc = new MarkupTagCompletion(provider, name);
if (desc.length() > 0) { if (desc.length() > 0) {
@@ -183,7 +178,7 @@ public class CompletionXMLParser extends DefaultHandler {
mc.setDefinedIn(definedIn); mc.setDefinedIn(definedIn);
return mc; return mc;
} }
private VariableCompletion createVariableCompletion() { private VariableCompletion createVariableCompletion() {
VariableCompletion vc = new VariableCompletion(provider, name, returnType); VariableCompletion vc = new VariableCompletion(provider, name, returnType);
if (desc.length() > 0) { if (desc.length() > 0) {
@@ -193,7 +188,7 @@ public class CompletionXMLParser extends DefaultHandler {
vc.setDefinedIn(definedIn); vc.setDefinedIn(definedIn);
return vc; return vc;
} }
/** /**
* Called when an element is closed. * Called when an element is closed.
*/ */
@@ -246,12 +241,12 @@ public class CompletionXMLParser extends DefaultHandler {
} }
} }
} }
@Override @Override
public void error(SAXParseException e) throws SAXException { public void error(SAXParseException e) throws SAXException {
throw e; throw e;
} }
/** /**
* Returns the completions found after parsing the XML. * Returns the completions found after parsing the XML.
* *
@@ -260,7 +255,7 @@ public class CompletionXMLParser extends DefaultHandler {
public List<Completion> getCompletions() { public List<Completion> getCompletions() {
return completions; return completions;
} }
/** /**
* Returns the parameter end character specified. * Returns the parameter end character specified.
* *
@@ -269,7 +264,7 @@ public class CompletionXMLParser extends DefaultHandler {
public char getParamEndChar() { public char getParamEndChar() {
return paramEndChar; return paramEndChar;
} }
/** /**
* Returns the parameter end string specified. * Returns the parameter end string specified.
* *
@@ -278,7 +273,7 @@ public class CompletionXMLParser extends DefaultHandler {
public String getParamSeparator() { public String getParamSeparator() {
return paramSeparator; return paramSeparator;
} }
/** /**
* Returns the parameter start character specified. * Returns the parameter start character specified.
* *
@@ -287,16 +282,15 @@ public class CompletionXMLParser extends DefaultHandler {
public char getParamStartChar() { public char getParamStartChar() {
return paramStartChar; return paramStartChar;
} }
private static final char getSingleChar(String str) { private static final char getSingleChar(String str) {
return str.length() == 1 ? str.charAt(0) : 0; return str.length() == 1 ? str.charAt(0) : 0;
} }
/** /**
* Resets this parser to grab more completions. * Resets this parser to grab more completions.
* *
* @param provider * @param provider The new provider to get completions for.
* The new provider to get completions for.
*/ */
public void reset(CompletionProvider provider) { public void reset(CompletionProvider provider) {
this.provider = provider; this.provider = provider;
@@ -305,28 +299,26 @@ public class CompletionXMLParser extends DefaultHandler {
paramStartChar = paramEndChar = 0; paramStartChar = paramEndChar = 0;
paramSeparator = null; paramSeparator = null;
} }
@Override @Override
public InputSource resolveEntity(String publicID, String systemID) throws SAXException { public InputSource resolveEntity(String publicID, String systemID) throws SAXException {
return new InputSource(getClass().getResourceAsStream("CompletionXml.dtd")); return new InputSource(getClass().getResourceAsStream("CompletionXml.dtd"));
} }
/** /**
* Sets the class loader to use when loading custom classes to use for * Sets the class loader to use when loading custom classes to use for various
* various {@link Completion} types, such as {@link FunctionCompletion}s, * {@link Completion} types, such as {@link FunctionCompletion}s, from XML.
* from XML.
* <p> * <p>
* *
* Users should very rarely have a need to use this method. * Users should very rarely have a need to use this method.
* *
* @param cl * @param cl The class loader to use. If this is <code>null</code>, then a
* The class loader to use. If this is <code>null</code>, then * default is used.
* a default is used.
*/ */
public static void setDefaultCompletionClassLoader(ClassLoader cl) { public static void setDefaultCompletionClassLoader(ClassLoader cl) {
DEFAULT_COMPLETION_CLASS_LOADER = cl; DEFAULT_COMPLETION_CLASS_LOADER = cl;
} }
/** /**
* Called when an element starts. * Called when an element starts.
*/ */
@@ -375,7 +367,7 @@ public class CompletionXMLParser extends DefaultHandler {
} }
} }
} }
@Override @Override
public void warning(SAXParseException e) throws SAXException { public void warning(SAXParseException e) throws SAXException {
throw e; throw e;
@@ -28,29 +28,29 @@ import org.xml.sax.SAXException;
/** /**
* A basic completion provider implementation. This provider has no * A basic completion provider implementation. This provider has no
* understanding of language semantics. It simply checks the text entered up * understanding of language semantics. It simply checks the text entered up to
* to the caret position for a match against known completions. This is all * the caret position for a match against known completions. This is all that is
* that is needed in the majority of cases. * needed in the majority of cases.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public class DefaultCompletionProvider extends AbstractCompletionProvider { public class DefaultCompletionProvider extends AbstractCompletionProvider {
protected Segment seg; protected Segment seg;
/** /**
* Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}. * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}.
*/ */
private String lastCompletionsAtText; private String lastCompletionsAtText;
/** /**
* Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}, * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}, since this
* since this may be called multiple times in succession (this is usually * may be called multiple times in succession (this is usually called by
* called by <tt>JTextComponent.getToolTipText()</tt>, and if the user * <tt>JTextComponent.getToolTipText()</tt>, and if the user wiggles the mouse
* wiggles the mouse while a tool tip is displayed, this method gets * while a tool tip is displayed, this method gets repeatedly called. It can be
* repeatedly called. It can be costly so we try to speed it up a tad). * costly so we try to speed it up a tad).
*/ */
private List<Completion> lastParameterizedCompletionsAt; private List<Completion> lastParameterizedCompletionsAt;
/** /**
* Constructor. The returned provider will not be aware of any completions. * Constructor. The returned provider will not be aware of any completions.
* *
@@ -59,28 +59,27 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
public DefaultCompletionProvider() { public DefaultCompletionProvider() {
init(); init();
} }
/** /**
* Creates a completion provider that provides completion for a simple * Creates a completion provider that provides completion for a simple list of
* list of words. * words.
* *
* @param words * @param words The words to offer as completion suggestions. If this is
* The words to offer as completion suggestions. If this is * <code>null</code>, no completions will be known.
* <code>null</code>, no completions will be known.
* @see BasicCompletion * @see BasicCompletion
*/ */
public DefaultCompletionProvider(String[] words) { public DefaultCompletionProvider(String[] words) {
init(); init();
addWordCompletions(words); addWordCompletions(words);
} }
/** /**
* Returns the text just before the current caret position that could be * Returns the text just before the current caret position that could be the
* the start of something auto-completable. * start of something auto-completable.
* <p> * <p>
* *
* This method returns all characters before the caret that are matched * This method returns all characters before the caret that are matched by
* by {@link #isValidChar(char)}. * {@link #isValidChar(char)}.
* *
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -108,7 +107,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
len = segEnd - start; len = segEnd - start;
return len == 0 ? EMPTY_STRING : new String(seg.array, start, len); return len == 0 ? EMPTY_STRING : new String(seg.array, start, len);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -156,7 +155,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
lastCompletionsAtText = null; lastCompletionsAtText = null;
return lastParameterizedCompletionsAt = null; return lastParameterizedCompletionsAt = null;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -212,36 +211,33 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
} }
return list; return list;
} }
/** /**
* Initializes this completion provider. * Initializes this completion provider.
*/ */
protected void init() { protected void init() {
seg = new Segment(); seg = new Segment();
} }
/** /**
* Returns whether the specified character is valid in an auto-completion. * Returns whether the specified character is valid in an auto-completion. The
* The default implementation is equivalent to * default implementation is equivalent to
* "<code>Character.isLetterOrDigit(ch) || ch=='_'</code>". Subclasses * "<code>Character.isLetterOrDigit(ch) || ch=='_'</code>". Subclasses can
* can override this method to change what characters are matched. * override this method to change what characters are matched.
* *
* @param ch * @param ch The character.
* The character.
* @return Whether the character is valid. * @return Whether the character is valid.
*/ */
protected boolean isValidChar(char ch) { protected boolean isValidChar(char ch) {
return Character.isLetterOrDigit(ch) || ch == '_'; return Character.isLetterOrDigit(ch) || ch == '_';
} }
/** /**
* Loads completions from an XML file. The XML should validate against * Loads completions from an XML file. The XML should validate against
* <code>CompletionXml.dtd</code>. * <code>CompletionXml.dtd</code>.
* *
* @param file * @param file An XML file to load from.
* An XML file to load from. * @throws IOException If an IO error occurs.
* @throws IOException
* If an IO error occurs.
*/ */
public void loadFromXML(File file) throws IOException { public void loadFromXML(File file) throws IOException {
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file)); BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file));
@@ -251,34 +247,28 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
bin.close(); bin.close();
} }
} }
/** /**
* Loads completions from an XML input stream. The XML should validate * Loads completions from an XML input stream. The XML should validate against
* against <code>CompletionXml.dtd</code>. * <code>CompletionXml.dtd</code>.
* *
* @param in * @param in The input stream to read from.
* The input stream to read from. * @throws IOException If an IO error occurs.
* @throws IOException
* If an IO error occurs.
*/ */
public void loadFromXML(InputStream in) throws IOException { public void loadFromXML(InputStream in) throws IOException {
loadFromXML(in, null); loadFromXML(in, null);
} }
/** /**
* Loads completions from an XML input stream. The XML should validate * Loads completions from an XML input stream. The XML should validate against
* against <code>CompletionXml.dtd</code>. * <code>CompletionXml.dtd</code>.
* *
* @param in * @param in The input stream to read from.
* The input stream to read from. * @param cl The class loader to use when loading any extra classes defined in
* @param cl * the XML, such as custom {@link FunctionCompletion}s. This may be
* The class loader to use when loading any extra classes defined * <code>null</code> if the default is to be used, or if no custom
* in the XML, such as custom {@link FunctionCompletion}s. This * completions are defined in the XML.
* may be <code>null</code> if the default is to be used, or if * @throws IOException If an IO error occurs.
* no
* custom completions are defined in the XML.
* @throws IOException
* If an IO error occurs.
*/ */
public void loadFromXML(InputStream in, ClassLoader cl) throws IOException { public void loadFromXML(InputStream in, ClassLoader cl) throws IOException {
// long start = System.currentTimeMillis(); // long start = System.currentTimeMillis();
@@ -309,15 +299,13 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
bin.close(); bin.close();
} }
} }
/** /**
* Loads completions from an XML file. The XML should validate against * Loads completions from an XML file. The XML should validate against
* <code>CompletionXml.dtd</code>. * <code>CompletionXml.dtd</code>.
* *
* @param resource * @param resource A resource the current ClassLoader can get to.
* A resource the current ClassLoader can get to. * @throws IOException If an IO error occurs.
* @throws IOException
* If an IO error occurs.
*/ */
public void loadFromXML(String resource) throws IOException { public void loadFromXML(String resource) throws IOException {
ClassLoader cl = getClass().getClassLoader(); ClassLoader cl = getClass().getClassLoader();
@@ -15,22 +15,22 @@ import javax.swing.JList;
import javax.swing.ListCellRenderer; import javax.swing.ListCellRenderer;
/** /**
* List cell renderer that delegates to a {@link CompletionProvider}'s * List cell renderer that delegates to a {@link CompletionProvider}'s renderer,
* renderer, if it has one. If it doesn't, it calls into a fallback renderer. * if it has one. If it doesn't, it calls into a fallback renderer. If a
* If a fallback renderer isn't specified, it simply renders * fallback renderer isn't specified, it simply renders
* <code>(({@link Completion})value).toString()</code>. * <code>(({@link Completion})value).toString()</code>.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
class DelegatingCellRenderer extends DefaultListCellRenderer { class DelegatingCellRenderer extends DefaultListCellRenderer {
/** /**
* The renderer to fall back on if one isn't specified by a provider. * The renderer to fall back on if one isn't specified by a provider. This is
* This is usually <tt>this</tt>. * usually <tt>this</tt>.
*/ */
private ListCellRenderer fallback; private ListCellRenderer fallback;
/** /**
* Returns the fallback cell renderer. * Returns the fallback cell renderer.
* *
@@ -40,12 +40,13 @@ class DelegatingCellRenderer extends DefaultListCellRenderer {
public ListCellRenderer getFallbackCellRenderer() { public ListCellRenderer getFallbackCellRenderer() {
return fallback; return fallback;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected, boolean hasFocus) { public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected,
boolean hasFocus) {
Completion c = (Completion) value; Completion c = (Completion) value;
CompletionProvider p = c.getProvider(); CompletionProvider p = c.getProvider();
ListCellRenderer r = p.getListCellRenderer(); ListCellRenderer r = p.getListCellRenderer();
@@ -57,19 +58,18 @@ class DelegatingCellRenderer extends DefaultListCellRenderer {
} }
return fallback.getListCellRendererComponent(list, value, index, selected, hasFocus); return fallback.getListCellRendererComponent(list, value, index, selected, hasFocus);
} }
/** /**
* Sets the fallback cell renderer. * Sets the fallback cell renderer.
* *
* @param fallback * @param fallback The fallback cell renderer. If this is <code>null</code>,
* The fallback cell renderer. If this is * <tt>this</tt> will be used.
* <code>null</code>, <tt>this</tt> will be used.
* @see #getFallbackCellRenderer() * @see #getFallbackCellRenderer()
*/ */
public void setFallbackCellRenderer(ListCellRenderer fallback) { public void setFallbackCellRenderer(ListCellRenderer fallback) {
this.fallback = fallback; this.fallback = fallback;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -14,15 +14,13 @@ package org.fife.ui.autocomplete;
* @see ExternalURLHandler * @see ExternalURLHandler
*/ */
public interface DescWindowCallback { public interface DescWindowCallback {
/** /**
* Callback allowing a new code completion's description to be displayed * Callback allowing a new code completion's description to be displayed in the
* in the description window. * description window.
* *
* @param completion * @param completion The new completion.
* The new completion. * @param anchor The anchor to scroll to, or <code>null</code> if none.
* @param anchor
* The anchor to scroll to, or <code>null</code> if none.
*/ */
public void showSummaryFor(Completion completion, String anchor); public void showSummaryFor(Completion completion, String anchor);
} }
+7 -6
View File
@@ -21,23 +21,24 @@ import javax.swing.Icon;
* @version 1.0 * @version 1.0
*/ */
public class EmptyIcon implements Icon, Serializable { public class EmptyIcon implements Icon, Serializable {
private int size; private int size;
public EmptyIcon(int size) { public EmptyIcon(int size) {
this.size = size; this.size = size;
} }
@Override @Override
public int getIconHeight() { public int getIconHeight() {
return size; return size;
} }
@Override @Override
public int getIconWidth() { public int getIconWidth() {
return size; return size;
} }
@Override @Override
public void paintIcon(Component c, Graphics g, int x, int y) {} public void paintIcon(Component c, Graphics g, int x, int y) {
}
} }
@@ -10,12 +10,12 @@ package org.fife.ui.autocomplete;
import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkEvent;
/** /**
* A callback for when an external URL is clicked in the description window. * A callback for when an external URL is clicked in the description window. If
* If no handler is installed, and if running in Java 6, the system default * no handler is installed, and if running in Java 6, the system default web
* web browser is used to open the URL. If not running Java 6, nothing will * browser is used to open the URL. If not running Java 6, nothing will happen.
* happen. If you want browser support for pre-Java 6 JRE's, you will need * If you want browser support for pre-Java 6 JRE's, you will need to register
* to register one of these callbacks on your {@link AutoCompletion}, and * one of these callbacks on your {@link AutoCompletion}, and open the URL in a
* open the URL in a web browser yourself. * web browser yourself.
* <p> * <p>
* *
* Alternatively, folks implementing robust code completion support for a * Alternatively, folks implementing robust code completion support for a
@@ -27,17 +27,13 @@ import javax.swing.event.HyperlinkEvent;
* @see AutoCompletion#setExternalURLHandler(ExternalURLHandler) * @see AutoCompletion#setExternalURLHandler(ExternalURLHandler)
*/ */
public interface ExternalURLHandler { public interface ExternalURLHandler {
/** /**
* Called when an external URL is clicked in the description window. * Called when an external URL is clicked in the description window.
* *
* @param e * @param e The event containing the hyperlink clicked.
* The event containing the hyperlink clicked. * @param c The completion currently being displayed.
* @param c * @param callback Allows you to display new content in the description window.
* The completion currently being displayed.
* @param callback
* Allows you to display new content in the description
* window.
*/ */
public void urlClicked(HyperlinkEvent e, Completion c, DescWindowCallback callback); public void urlClicked(HyperlinkEvent e, Completion c, DescWindowCallback callback);
} }
+27 -29
View File
@@ -20,37 +20,37 @@ import javax.swing.plaf.basic.BasicListUI;
/** /**
* A custom list UI, used by the completion choices list. If the number of * A custom list UI, used by the completion choices list. If the number of
* completion choices is "large," it does a fast estimate of the preferred * completion choices is "large," it does a fast estimate of the preferred width
* width and height of list items. This allows HTML renderers to be used (such * and height of list items. This allows HTML renderers to be used (such as
* as {@link CompletionCellRenderer}), with thousands of completion choices, * {@link CompletionCellRenderer}), with thousands of completion choices, with
* with no performance penalty. With standard BasicListUI subclasses, this can * no performance penalty. With standard BasicListUI subclasses, this can cause
* cause very poor performance <b>each time</b> the list is displayed, which * very poor performance <b>each time</b> the list is displayed, which is bad
* is bad for lists that are repeatedly hidden and re-displayed, such as * for lists that are repeatedly hidden and re-displayed, such as completion
* completion choices. This is all because the calculation to get the * choices. This is all because the calculation to get the preferred size of
* preferred size of each list item, when it is displayed with HTML, is slow. * each list item, when it is displayed with HTML, is slow.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
class FastListUI extends BasicListUI { class FastListUI extends BasicListUI {
/** /**
* Whether the selection background was overridden (usually because of * Whether the selection background was overridden (usually because of Nimbus)
* Nimbus) so we know to manually uninstall the color we installed. * so we know to manually uninstall the color we installed.
*/ */
private boolean overriddenBackground; private boolean overriddenBackground;
/** /**
* Whether the selection foreground was overridden (usually because of * Whether the selection foreground was overridden (usually because of Nimbus)
* Nimbus) so we know to manually uninstall the color we installed. * so we know to manually uninstall the color we installed.
*/ */
private boolean overriddenForeground; private boolean overriddenForeground;
/** /**
* If there are more than this many completions in a single list, this * If there are more than this many completions in a single list, this UI will
* UI will estimate the cell width and height needed for each item instead * estimate the cell width and height needed for each item instead of computing
* of computing it, for performance reasons. * it, for performance reasons.
*/ */
private static final int ESTIMATION_THRESHOLD = 200; private static final int ESTIMATION_THRESHOLD = 200;
private Color determineSelectionBackground() { private Color determineSelectionBackground() {
Color c = UIManager.getColor("List.selectionBackground"); Color c = UIManager.getColor("List.selectionBackground");
if (c == null) { if (c == null) {
@@ -68,7 +68,7 @@ class FastListUI extends BasicListUI {
// actually be a ColorUIResource // actually be a ColorUIResource
return new Color(c.getRGB());// new ColorUIResource(c); return new Color(c.getRGB());// new ColorUIResource(c);
} }
private Color determineSelectionForeground() { private Color determineSelectionForeground() {
Color c = UIManager.getColor("List.selectionForeground"); Color c = UIManager.getColor("List.selectionForeground");
if (c == null) { if (c == null) {
@@ -84,12 +84,11 @@ class FastListUI extends BasicListUI {
// may actually be a ColorUIResource // may actually be a ColorUIResource
return new Color(c.getRGB()); return new Color(c.getRGB());
} }
/** /**
* Overridden to ensure we have selection background/foreground colors * Overridden to ensure we have selection background/foreground colors defined,
* defined, even if we're in some weirdo LAF such as Nimbus which doesn't * even if we're in some weirdo LAF such as Nimbus which doesn't define them.
* define them. Since FastListUI extends BasicListUI, we need these values * Since FastListUI extends BasicListUI, we need these values to be defined.
* to be defined.
*/ */
@Override @Override
protected void installDefaults() { protected void installDefaults() {
@@ -103,7 +102,7 @@ class FastListUI extends BasicListUI {
overriddenForeground = true; overriddenForeground = true;
} }
} }
/** /**
* Overridden to work around a Nimbus issue. * Overridden to work around a Nimbus issue.
*/ */
@@ -117,12 +116,11 @@ class FastListUI extends BasicListUI {
list.setSelectionForeground(null); list.setSelectionForeground(null);
} }
} }
/** /**
* Recalculates the cell width and height of each cell in the list. This * Recalculates the cell width and height of each cell in the list. This method
* method is overridden to do a fast estimation if the completion list is * is overridden to do a fast estimation if the completion list is too long, to
* too long, to improve performance for lists with huge amounts of * improve performance for lists with huge amounts of completions.
* completions.
*/ */
@Override @Override
protected void updateLayoutState() { protected void updateLayoutState() {
@@ -20,7 +20,7 @@ import javax.swing.text.Position;
* @version 1.0 * @version 1.0
*/ */
public class FunctionCompletion extends VariableCompletion implements ParameterizedCompletion { public class FunctionCompletion extends VariableCompletion implements ParameterizedCompletion {
/** /**
* Parameters to the function. * Parameters to the function.
*/ */
@@ -33,33 +33,29 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
* Used to improve performance of sorting FunctionCompletions. * Used to improve performance of sorting FunctionCompletions.
*/ */
private String compareString; private String compareString;
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The parent provider.
* The parent provider. * @param name The name of this function.
* @param name * @param returnType The return type of this function.
* The name of this function.
* @param returnType
* The return type of this function.
*/ */
public FunctionCompletion(CompletionProvider provider, String name, String returnType) { public FunctionCompletion(CompletionProvider provider, String name, String returnType) {
super(provider, name, returnType); super(provider, name, returnType);
} }
@Override @Override
protected void addDefinitionString(StringBuilder sb) { protected void addDefinitionString(StringBuilder sb) {
sb.append("<html><b>"); sb.append("<html><b>");
sb.append(getDefinitionString()); sb.append(getDefinitionString());
sb.append("</b>"); sb.append("</b>");
} }
/** /**
* Adds HTML describing the parameters to this function to a buffer. * Adds HTML describing the parameters to this function to a buffer.
* *
* @param sb * @param sb The buffer to append to.
* The buffer to append to.
*/ */
protected void addParameters(StringBuilder sb) { protected void addParameters(StringBuilder sb) {
// TODO: Localize me // TODO: Localize me
@@ -86,12 +82,11 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
sb.append("</td></tr></table></center><br><br>"); sb.append("</td></tr></table></center><br><br>");
} }
} }
/** /**
* Overridden to compare methods by their comparison strings. * Overridden to compare methods by their comparison strings.
* *
* @param c2 * @param c2 A <code>Completion</code> to compare to.
* A <code>Completion</code> to compare to.
* @return The sort order. * @return The sort order.
*/ */
@Override @Override
@@ -106,7 +101,7 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
} }
return rc; return rc;
} }
/** /**
* Returns a string used to compare this method completion to another. * Returns a string used to compare this method completion to another.
* *
@@ -114,11 +109,9 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
*/ */
private String getCompareString() { private String getCompareString() {
/* /*
* This string compares the following parts of methods in this order, * This string compares the following parts of methods in this order, to
* to optimize sort order in completion lists. * optimize sort order in completion lists. 1. First, by name 2. Next, by number
* 1. First, by name * of parameters. 3. Finally, by parameter type.
* 2. Next, by number of parameters.
* 3. Finally, by parameter type.
*/ */
if (compareString == null) { if (compareString == null) {
StringBuilder sb = new StringBuilder(getName()); StringBuilder sb = new StringBuilder(getName());
@@ -139,10 +132,10 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
} }
return compareString; return compareString;
} }
/** /**
* Returns the "definition string" for this function completion. For * Returns the "definition string" for this function completion. For example,
* example, for the C "<code>printf</code>" function, this would return * for the C "<code>printf</code>" function, this would return
* "<code>int printf(const char *, ...)</code>". * "<code>int printf(const char *, ...)</code>".
* *
* @return The definition string. * @return The definition string.
@@ -186,7 +179,7 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
} }
return sb.toString(); return sb.toString();
} }
@Override @Override
public ParameterizedCompletionInsertionInfo getInsertionInfo(JTextComponent tc, boolean replaceTabsWithSpaces) { public ParameterizedCompletionInsertionInfo getInsertionInfo(JTextComponent tc, boolean replaceTabsWithSpaces) {
ParameterizedCompletionInsertionInfo info = new ParameterizedCompletionInsertionInfo(); ParameterizedCompletionInsertionInfo info = new ParameterizedCompletionInsertionInfo();
@@ -238,7 +231,7 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
info.setTextToInsert(sb.toString()); info.setTextToInsert(sb.toString());
return info; return info;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -246,7 +239,7 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
public Parameter getParam(int index) { public Parameter getParam(int index) {
return params.get(index); return params.get(index);
} }
/** /**
* Returns the number of parameters to this function. * Returns the number of parameters to this function.
* *
@@ -257,7 +250,7 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
public int getParamCount() { public int getParamCount() {
return params == null ? 0 : params.size(); return params == null ? 0 : params.size();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -265,12 +258,11 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
public boolean getShowParameterToolTip() { public boolean getShowParameterToolTip() {
return true; return true;
} }
/** /**
* Returns the text to insert for a parameter. * Returns the text to insert for a parameter.
* *
* @param param * @param param The parameter.
* The parameter.
* @return The text. * @return The text.
*/ */
private String getParamText(ParameterizedCompletion.Parameter param) { private String getParamText(ParameterizedCompletion.Parameter param) {
@@ -283,7 +275,7 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
} }
return text; return text;
} }
/** /**
* Returns the description of the return value of this function. * Returns the description of the return value of this function.
* *
@@ -293,7 +285,7 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
public String getReturnValueDescription() { public String getReturnValueDescription() {
return returnValDesc; return returnValDesc;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -308,7 +300,7 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
possiblyAddDefinedIn(sb); possiblyAddDefinedIn(sb);
return sb.toString(); return sb.toString();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -320,13 +312,12 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
} }
return text; return text;
} }
/** /**
* Sets the parameters to this function. * Sets the parameters to this function.
* *
* @param params * @param params The parameters. This should be a list of
* The parameters. This should be a list of * {@link ParameterizedCompletion.Parameter}s.
* {@link ParameterizedCompletion.Parameter}s.
* @see #getParam(int) * @see #getParam(int)
* @see #getParamCount() * @see #getParamCount()
*/ */
@@ -336,12 +327,11 @@ public class FunctionCompletion extends VariableCompletion implements Parameteri
this.params = new ArrayList<Parameter>(params); this.params = new ArrayList<Parameter>(params);
} }
} }
/** /**
* Sets the description of the return value of this function. * Sets the description of the return value of this function.
* *
* @param desc * @param desc The description.
* The description.
* @see #getReturnValueDescription() * @see #getReturnValueDescription()
*/ */
public void setReturnValueDescription(String desc) { public void setReturnValueDescription(String desc) {
@@ -33,13 +33,13 @@ import org.fife.ui.rtextarea.ToolTipSupplier;
* <li>A documentation comment</li> * <li>A documentation comment</li>
* </ul> * </ul>
* *
* This allows for different completion choices in comments than in code, * This allows for different completion choices in comments than in code, for
* for example. * example.
* <p> * <p>
* *
* This provider also implements the * This provider also implements the
* <tt>org.fife.ui.rtextarea.ToolTipSupplier</tt> interface, which allows it * <tt>org.fife.ui.rtextarea.ToolTipSupplier</tt> interface, which allows it to
* to display tooltips for completion choices. Thus the standard * display tooltips for completion choices. Thus the standard
* {@link VariableCompletion} and {@link FunctionCompletion} completions should * {@link VariableCompletion} and {@link FunctionCompletion} completions should
* be able to display tooltips with the variable declaration or function * be able to display tooltips with the variable declaration or function
* definition (provided the <tt>RSyntaxTextArea</tt> was registered with the * definition (provided the <tt>RSyntaxTextArea</tt> was registered with the
@@ -49,10 +49,9 @@ import org.fife.ui.rtextarea.ToolTipSupplier;
* @version 1.0 * @version 1.0
*/ */
public class LanguageAwareCompletionProvider extends CompletionProviderBase implements ToolTipSupplier { public class LanguageAwareCompletionProvider extends CompletionProviderBase implements ToolTipSupplier {
/** /**
* The provider to use when no provider is assigned to a particular token * The provider to use when no provider is assigned to a particular token type.
* type.
*/ */
private CompletionProvider defaultProvider; private CompletionProvider defaultProvider;
/** /**
@@ -67,41 +66,40 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
* The provider to use while in documentation comments. * The provider to use while in documentation comments.
*/ */
private CompletionProvider docCommentCompletionProvider; private CompletionProvider docCommentCompletionProvider;
/** /**
* Constructor subclasses can use when they don't have their default * Constructor subclasses can use when they don't have their default provider
* provider created at construction time. They should call * created at construction time. They should call
* {@link #setDefaultCompletionProvider(CompletionProvider)} in this * {@link #setDefaultCompletionProvider(CompletionProvider)} in this
* constructor. * constructor.
*/ */
protected LanguageAwareCompletionProvider() {} protected LanguageAwareCompletionProvider() {
}
/** /**
* Constructor. * Constructor.
* *
* @param defaultProvider * @param defaultProvider The provider to use when no provider is assigned to a
* The provider to use when no provider is assigned * particular token type. This cannot be
* to a particular token type. This cannot be <code>null</code>. * <code>null</code>.
*/ */
public LanguageAwareCompletionProvider(CompletionProvider defaultProvider) { public LanguageAwareCompletionProvider(CompletionProvider defaultProvider) {
setDefaultCompletionProvider(defaultProvider); setDefaultCompletionProvider(defaultProvider);
} }
/** /**
* Calling this method will result in an * Calling this method will result in an {@link UnsupportedOperationException}
* {@link UnsupportedOperationException} being thrown. To set the * being thrown. To set the parameter completion parameters, do so on the
* parameter completion parameters, do so on the provider returned by * provider returned by {@link #getDefaultCompletionProvider()}.
* {@link #getDefaultCompletionProvider()}.
* *
* @throws UnsupportedOperationException * @throws UnsupportedOperationException Always.
* Always.
* @see #setParameterizedCompletionParams(char, String, char) * @see #setParameterizedCompletionParams(char, String, char)
*/ */
@Override @Override
public void clearParameterizedCompletionParams() { public void clearParameterizedCompletionParams() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -113,7 +111,7 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
CompletionProvider provider = getProviderFor(comp); CompletionProvider provider = getProviderFor(comp);
return provider != null ? provider.getAlreadyEnteredText(comp) : null; return provider != null ? provider.getAlreadyEnteredText(comp) : null;
} }
/** /**
* Returns the completion provider to use for comments. * Returns the completion provider to use for comments.
* *
@@ -123,7 +121,7 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
public CompletionProvider getCommentCompletionProvider() { public CompletionProvider getCommentCompletionProvider() {
return commentCompletionProvider; return commentCompletionProvider;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -131,14 +129,12 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
public List<Completion> getCompletionsAt(JTextComponent tc, Point p) { public List<Completion> getCompletionsAt(JTextComponent tc, Point p) {
return defaultProvider == null ? null : defaultProvider.getCompletionsAt(tc, p); return defaultProvider == null ? null : defaultProvider.getCompletionsAt(tc, p);
} }
/** /**
* Does the dirty work of creating a list of completions. * Does the dirty work of creating a list of completions.
* *
* @param comp * @param comp The text component to look in.
* The text component to look in. * @return The list of possible completions, or an empty list if there are none.
* @return The list of possible completions, or an empty list if there
* are none.
*/ */
@Override @Override
protected List<Completion> getCompletionsImpl(JTextComponent comp) { protected List<Completion> getCompletionsImpl(JTextComponent comp) {
@@ -150,10 +146,10 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
} }
return Collections.emptyList(); return Collections.emptyList();
} }
/** /**
* Returns the completion provider used when one isn't defined for a * Returns the completion provider used when one isn't defined for a particular
* particular token type. * token type.
* *
* @return The completion provider to use. * @return The completion provider to use.
* @see #setDefaultCompletionProvider(CompletionProvider) * @see #setDefaultCompletionProvider(CompletionProvider)
@@ -161,7 +157,7 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
public CompletionProvider getDefaultCompletionProvider() { public CompletionProvider getDefaultCompletionProvider() {
return defaultProvider; return defaultProvider;
} }
/** /**
* Returns the completion provider to use for documentation comments. * Returns the completion provider to use for documentation comments.
* *
@@ -171,7 +167,7 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
public CompletionProvider getDocCommentCompletionProvider() { public CompletionProvider getDocCommentCompletionProvider() {
return docCommentCompletionProvider; return docCommentCompletionProvider;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -183,7 +179,7 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
CompletionProvider provider = getProviderFor(tc); CompletionProvider provider = getProviderFor(tc);
return provider == defaultProvider ? provider.getParameterizedCompletions(tc) : null; return provider == defaultProvider ? provider.getParameterizedCompletions(tc) : null;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -191,7 +187,7 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
public char getParameterListEnd() { public char getParameterListEnd() {
return defaultProvider.getParameterListEnd(); return defaultProvider.getParameterListEnd();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -199,7 +195,7 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
public String getParameterListSeparator() { public String getParameterListSeparator() {
return defaultProvider.getParameterListSeparator(); return defaultProvider.getParameterListSeparator();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -207,13 +203,12 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
public char getParameterListStart() { public char getParameterListStart() {
return defaultProvider.getParameterListStart(); return defaultProvider.getParameterListStart();
} }
/** /**
* Returns the completion provider to use at the current caret position in * Returns the completion provider to use at the current caret position in a
* a text component. * text component.
* *
* @param comp * @param comp The text component to check.
* The text component to check.
* @return The completion provider to use. * @return The completion provider to use.
*/ */
private CompletionProvider getProviderFor(JTextComponent comp) { private CompletionProvider getProviderFor(JTextComponent comp) {
@@ -242,15 +237,15 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
type = doc.getClosestStandardTokenTypeForInternalType(type); type = doc.getClosestStandardTokenTypeForInternalType(type);
} }
switch (type) { switch (type) {
case Token.ERROR_STRING_DOUBLE: case Token.ERROR_STRING_DOUBLE:
return getStringCompletionProvider(); return getStringCompletionProvider();
case Token.COMMENT_EOL: case Token.COMMENT_EOL:
case Token.COMMENT_MULTILINE: case Token.COMMENT_MULTILINE:
return getCommentCompletionProvider(); return getCommentCompletionProvider();
case Token.COMMENT_DOCUMENTATION: case Token.COMMENT_DOCUMENTATION:
return getDocCommentCompletionProvider(); return getDocCommentCompletionProvider();
default: default:
return getDefaultCompletionProvider(); return getDefaultCompletionProvider();
} }
} }
// FIXME: This isn't always a safe assumption. // FIXME: This isn't always a safe assumption.
@@ -261,27 +256,27 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
return getDefaultCompletionProvider(); return getDefaultCompletionProvider();
} }
switch (curToken.getType()) { switch (curToken.getType()) {
case Token.LITERAL_STRING_DOUBLE_QUOTE: case Token.LITERAL_STRING_DOUBLE_QUOTE:
case Token.ERROR_STRING_DOUBLE: case Token.ERROR_STRING_DOUBLE:
return getStringCompletionProvider(); return getStringCompletionProvider();
case Token.COMMENT_EOL: case Token.COMMENT_EOL:
case Token.COMMENT_MULTILINE: case Token.COMMENT_MULTILINE:
return getCommentCompletionProvider(); return getCommentCompletionProvider();
case Token.COMMENT_DOCUMENTATION: case Token.COMMENT_DOCUMENTATION:
return getDocCommentCompletionProvider(); return getDocCommentCompletionProvider();
case Token.NULL: case Token.NULL:
case Token.WHITESPACE: case Token.WHITESPACE:
case Token.IDENTIFIER: case Token.IDENTIFIER:
case Token.VARIABLE: case Token.VARIABLE:
case Token.PREPROCESSOR: case Token.PREPROCESSOR:
case Token.DATA_TYPE: case Token.DATA_TYPE:
case Token.FUNCTION: case Token.FUNCTION:
case Token.OPERATOR: case Token.OPERATOR:
return getDefaultCompletionProvider(); return getDefaultCompletionProvider();
} }
return null; // In a token type we can't auto-complete from. return null; // In a token type we can't auto-complete from.
} }
/** /**
* Returns the completion provider to use for strings. * Returns the completion provider to use for strings.
* *
@@ -291,7 +286,7 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
public CompletionProvider getStringCompletionProvider() { public CompletionProvider getStringCompletionProvider() {
return stringCompletionProvider; return stringCompletionProvider;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -300,24 +295,22 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
CompletionProvider provider = getProviderFor(tc); CompletionProvider provider = getProviderFor(tc);
return provider != null ? provider.isAutoActivateOkay(tc) : false; return provider != null ? provider.isAutoActivateOkay(tc) : false;
} }
/** /**
* Sets the comment completion provider. * Sets the comment completion provider.
* *
* @param provider * @param provider The provider to use in comments.
* The provider to use in comments.
* @see #getCommentCompletionProvider() * @see #getCommentCompletionProvider()
*/ */
public void setCommentCompletionProvider(CompletionProvider provider) { public void setCommentCompletionProvider(CompletionProvider provider) {
this.commentCompletionProvider = provider; this.commentCompletionProvider = provider;
} }
/** /**
* Sets the default completion provider. * Sets the default completion provider.
* *
* @param provider * @param provider The provider to use when no provider is assigned to a
* The provider to use when no provider is assigned to a * particular token type. This cannot be <code>null</code>.
* particular token type. This cannot be <code>null</code>.
* @see #getDefaultCompletionProvider() * @see #getDefaultCompletionProvider()
*/ */
public void setDefaultCompletionProvider(CompletionProvider provider) { public void setDefaultCompletionProvider(CompletionProvider provider) {
@@ -326,59 +319,53 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase impl
} }
this.defaultProvider = provider; this.defaultProvider = provider;
} }
/** /**
* Sets the documentation comment completion provider. * Sets the documentation comment completion provider.
* *
* @param provider * @param provider The provider to use in comments.
* The provider to use in comments.
* @see #getDocCommentCompletionProvider() * @see #getDocCommentCompletionProvider()
*/ */
public void setDocCommentCompletionProvider(CompletionProvider provider) { public void setDocCommentCompletionProvider(CompletionProvider provider) {
this.docCommentCompletionProvider = provider; this.docCommentCompletionProvider = provider;
} }
/** /**
* Calling this method will result in an * Calling this method will result in an {@link UnsupportedOperationException}
* {@link UnsupportedOperationException} being thrown. To set the * being thrown. To set the parameter completion parameters, do so on the
* parameter completion parameters, do so on the provider returned by * provider returned by {@link #getDefaultCompletionProvider()}.
* {@link #getDefaultCompletionProvider()}.
* *
* @throws UnsupportedOperationException * @throws UnsupportedOperationException Always.
* Always.
* @see #clearParameterizedCompletionParams() * @see #clearParameterizedCompletionParams()
*/ */
@Override @Override
public void setParameterizedCompletionParams(char listStart, String separator, char listEnd) { public void setParameterizedCompletionParams(char listStart, String separator, char listEnd) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/** /**
* Sets the completion provider to use while in a string. * Sets the completion provider to use while in a string.
* *
* @param provider * @param provider The provider to use.
* The provider to use.
* @see #getStringCompletionProvider() * @see #getStringCompletionProvider()
*/ */
public void setStringCompletionProvider(CompletionProvider provider) { public void setStringCompletionProvider(CompletionProvider provider) {
stringCompletionProvider = provider; stringCompletionProvider = provider;
} }
/** /**
* Returns the tool tip to display for a mouse event. * Returns the tool tip to display for a mouse event.
* <p> * <p>
* *
* For this method to be called, the <tt>RSyntaxTextArea</tt> must be * For this method to be called, the <tt>RSyntaxTextArea</tt> must be registered
* registered with the <tt>javax.swing.ToolTipManager</tt> like so: * with the <tt>javax.swing.ToolTipManager</tt> like so:
* *
* <pre> * <pre>
* ToolTipManager.sharedInstance().registerComponent(textArea); * ToolTipManager.sharedInstance().registerComponent(textArea);
* </pre> * </pre>
* *
* @param textArea * @param textArea The text area.
* The text area. * @param e The mouse event.
* @param e
* The mouse event.
* @return The tool tip text, or <code>null</code> if none. * @return The tool tip text, or <code>null</code> if none.
*/ */
@Override @Override
@@ -8,14 +8,13 @@ package org.fife.ui.autocomplete;
import java.net.URL; import java.net.URL;
/** /**
* Possibly redirects one URL to another. Useful if you want "external" URL's * Possibly redirects one URL to another. Useful if you want "external" URL's in
* in code completion documentation to point to a local copy instead, for * code completion documentation to point to a local copy instead, for example.
* example.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public interface LinkRedirector { public interface LinkRedirector {
public URL possiblyRedirect(URL original); public URL possiblyRedirect(URL original);
} }
@@ -19,7 +19,7 @@ import org.fife.ui.autocomplete.ParameterizedCompletion.Parameter;
* @version 1.0 * @version 1.0
*/ */
public class MarkupTagCompletion extends AbstractCompletion { public class MarkupTagCompletion extends AbstractCompletion {
private String name; private String name;
private String desc; private String desc;
private String definedIn; private String definedIn;
@@ -27,25 +27,22 @@ public class MarkupTagCompletion extends AbstractCompletion {
* Attributes of the tag. * Attributes of the tag.
*/ */
private List<Parameter> attrs; private List<Parameter> attrs;
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The parent provider instance.
* The parent provider instance. * @param name The name of the tag.
* @param name
* The name of the tag.
*/ */
public MarkupTagCompletion(CompletionProvider provider, String name) { public MarkupTagCompletion(CompletionProvider provider, String name) {
super(provider); super(provider);
this.name = name; this.name = name;
} }
/** /**
* Adds HTML describing the attributes of this tag to a buffer. * Adds HTML describing the attributes of this tag to a buffer.
* *
* @param sb * @param sb The buffer to append to.
* The buffer to append to.
*/ */
protected void addAttributes(StringBuilder sb) { protected void addAttributes(StringBuilder sb) {
// TODO: Localize me. // TODO: Localize me.
@@ -67,11 +64,11 @@ public class MarkupTagCompletion extends AbstractCompletion {
sb.append("</td></tr></table></center><br><br>"); sb.append("</td></tr></table></center><br><br>");
} }
} }
protected void addDefinitionString(StringBuilder sb) { protected void addDefinitionString(StringBuilder sb) {
sb.append("<html><b>").append(name).append("</b>"); sb.append("<html><b>").append(name).append("</b>");
} }
/** /**
* Returns all attributes of this tag. * Returns all attributes of this tag.
* *
@@ -82,19 +79,18 @@ public class MarkupTagCompletion extends AbstractCompletion {
public List<Parameter> getAttributes() { public List<Parameter> getAttributes() {
return attrs; return attrs;
} }
/** /**
* Returns the specified {@link ParameterizedCompletion.Parameter}. * Returns the specified {@link ParameterizedCompletion.Parameter}.
* *
* @param index * @param index The index of the attribute to retrieve.
* The index of the attribute to retrieve.
* @return The attribute. * @return The attribute.
* @see #getAttributeCount() * @see #getAttributeCount()
*/ */
public Parameter getAttribute(int index) { public Parameter getAttribute(int index) {
return attrs.get(index); return attrs.get(index);
} }
/** /**
* Returns the number of attributes of this tag. * Returns the number of attributes of this tag.
* *
@@ -104,7 +100,7 @@ public class MarkupTagCompletion extends AbstractCompletion {
public int getAttributeCount() { public int getAttributeCount() {
return attrs == null ? 0 : attrs.size(); return attrs == null ? 0 : attrs.size();
} }
/** /**
* Returns where this variable is defined. * Returns where this variable is defined.
* *
@@ -114,19 +110,17 @@ public class MarkupTagCompletion extends AbstractCompletion {
public String getDefinedIn() { public String getDefinedIn() {
return definedIn; return definedIn;
} }
/** /**
* Returns a short description of this variable. This should be an * Returns a short description of this variable. This should be an HTML snippet.
* HTML snippet.
* *
* @return A short description of this variable. This may be * @return A short description of this variable. This may be <code>null</code>.
* <code>null</code>.
* @see #setDescription(String) * @see #setDescription(String)
*/ */
public String getDescription() { public String getDescription() {
return desc; return desc;
} }
/** /**
* Returns the name of this tag. * Returns the name of this tag.
* *
@@ -135,7 +129,7 @@ public class MarkupTagCompletion extends AbstractCompletion {
public String getName() { public String getName() {
return name; return name;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -143,7 +137,7 @@ public class MarkupTagCompletion extends AbstractCompletion {
public String getReplacementText() { public String getReplacementText() {
return getName(); return getName();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -156,13 +150,12 @@ public class MarkupTagCompletion extends AbstractCompletion {
possiblyAddDefinedIn(sb); possiblyAddDefinedIn(sb);
return sb.toString(); return sb.toString();
} }
/** /**
* Adds some HTML describing where this variable is defined, if this * Adds some HTML describing where this variable is defined, if this information
* information is known. * is known.
* *
* @param sb * @param sb The buffer to append to.
* The buffer to append to.
*/ */
protected void possiblyAddDefinedIn(StringBuilder sb) { protected void possiblyAddDefinedIn(StringBuilder sb) {
if (definedIn != null) { if (definedIn != null) {
@@ -170,13 +163,11 @@ public class MarkupTagCompletion extends AbstractCompletion {
sb.append(" <em>").append(definedIn).append("</em>"); sb.append(" <em>").append(definedIn).append("</em>");
} }
} }
/** /**
* Adds the description text as HTML to a buffer, if a description is * Adds the description text as HTML to a buffer, if a description is defined.
* defined.
* *
* @param sb * @param sb The buffer to append to.
* The buffer to append to.
*/ */
protected void possiblyAddDescription(StringBuilder sb) { protected void possiblyAddDescription(StringBuilder sb) {
if (desc != null) { if (desc != null) {
@@ -185,36 +176,31 @@ public class MarkupTagCompletion extends AbstractCompletion {
sb.append("<br><br><br>"); sb.append("<br><br><br>");
} }
} }
/** /**
* Sets where this variable is defined. * Sets where this variable is defined.
* *
* @param definedIn * @param definedIn Where this variable is defined.
* Where this variable is defined.
* @see #getDefinedIn() * @see #getDefinedIn()
*/ */
public void setDefinedIn(String definedIn) { public void setDefinedIn(String definedIn) {
this.definedIn = definedIn; this.definedIn = definedIn;
} }
/** /**
* Sets the short description of this tag. This should be an * Sets the short description of this tag. This should be an HTML snippet.
* HTML snippet.
* *
* @param desc * @param desc A short description of this tag. This may be <code>null</code>.
* A short description of this tag. This may be
* <code>null</code>.
* @see #getDescription() * @see #getDescription()
*/ */
public void setDescription(String desc) { public void setDescription(String desc) {
this.desc = desc; this.desc = desc;
} }
/** /**
* Sets the attributes of this tag. * Sets the attributes of this tag.
* *
* @param attrs * @param attrs The attributes.
* The attributes.
* @see #getAttribute(int) * @see #getAttribute(int)
* @see #getAttributeCount() * @see #getAttributeCount()
*/ */
@@ -19,40 +19,39 @@ import javax.swing.text.Position;
import javax.swing.text.View; import javax.swing.text.View;
/** /**
* Highlight painter that draws an outline around the text. This is used to * Highlight painter that draws an outline around the text. This is used to draw
* draw bounds around function/method parameters. * bounds around function/method parameters.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
/* /*
* NOTE: Whenever you see text like "Workaround for Java Highlight issues", * NOTE: Whenever you see text like "Workaround for Java Highlight issues", this
* this is because highlighted text in a JTextComponent gets "pushed" forward * is because highlighted text in a JTextComponent gets "pushed" forward when
* when the caret is at the Highlight's start, when we need it to instead get * the caret is at the Highlight's start, when we need it to instead get
* prepended to. For this reason, the auto-complete package adds its Highlights * prepended to. For this reason, the auto-complete package adds its Highlights
* 1 char too long (1 char earlier than where it should really start), but only * 1 char too long (1 char earlier than where it should really start), but only
* paint the Highlight from the 2nd char on. * paint the Highlight from the 2nd char on.
*/ */
class OutlineHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter { class OutlineHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter {
/** /**
* DefaultHighlightPainter doesn't allow changing color, so we must cache * DefaultHighlightPainter doesn't allow changing color, so we must cache ours
* ours here. * here.
*/ */
private Color color; private Color color;
/** /**
* Constructor. * Constructor.
* *
* @param color * @param color The color to draw the bounding boxes with. This cannot be
* The color to draw the bounding boxes with. This cannot * <code>null</code>.
* be <code>null</code>.
*/ */
public OutlineHighlightPainter(Color color) { public OutlineHighlightPainter(Color color) {
super(color); super(color);
setColor(color); setColor(color);
} }
/** /**
* Returns the color to paint bounding boxes with. * Returns the color to paint bounding boxes with.
* *
@@ -63,7 +62,7 @@ class OutlineHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter
public Color getColor() { public Color getColor() {
return color; return color;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -110,12 +109,11 @@ class OutlineHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter
return null; return null;
} }
} }
/** /**
* Sets the color to paint the bounding boxes with. * Sets the color to paint the bounding boxes with.
* *
* @param color * @param color The new color. This cannot be <code>null</code>.
* The new color. This cannot be <code>null</code>.
* @see #getColor() * @see #getColor()
*/ */
public void setColor(Color color) { public void setColor(Color color) {
@@ -12,25 +12,23 @@ import java.util.List;
import javax.swing.text.JTextComponent; import javax.swing.text.JTextComponent;
/** /**
* Provides completions for a {@link ParameterizedCompletion}'s parameters. * Provides completions for a {@link ParameterizedCompletion}'s parameters. So,
* So, for example, if the user code-completes a function or method, if * for example, if the user code-completes a function or method, if a
* a <code>ParameterChoicesProvider</code> is installed, it can return possible * <code>ParameterChoicesProvider</code> is installed, it can return possible
* completions for the parameters to that function or method. * completions for the parameters to that function or method.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public interface ParameterChoicesProvider { public interface ParameterChoicesProvider {
/** /**
* Returns a list of choices for a specific parameter. * Returns a list of choices for a specific parameter.
* *
* @param tc * @param tc The text component.
* The text component. * @param param The currently focused parameter.
* @param param * @return The list of parameters. This may be <code>null</code> for "no
* The currently focused parameter. * parameters," but might also be an empty list.
* @return The list of parameters. This may be <code>null</code> for
* "no parameters," but might also be an empty list.
*/ */
public List<Completion> getParameterChoices(JTextComponent tc, ParameterizedCompletion.Parameter param); public List<Completion> getParameterChoices(JTextComponent tc, ParameterizedCompletion.Parameter param);
} }
@@ -15,26 +15,25 @@ import javax.swing.text.JTextComponent;
* @version 1.0 * @version 1.0
*/ */
public interface ParameterizedCompletion extends Completion { public interface ParameterizedCompletion extends Completion {
/** /**
* Returns the "definition string" for this completion. For example, * Returns the "definition string" for this completion. For example, for the C
* for the C "<code>printf</code>" function, this would return * "<code>printf</code>" function, this would return
* "<code>int printf(const char *, ...)</code>". * "<code>int printf(const char *, ...)</code>".
* *
* @return The definition string. * @return The definition string.
*/ */
public String getDefinitionString(); public String getDefinitionString();
/** /**
* Returns the specified {@link Parameter}. * Returns the specified {@link Parameter}.
* *
* @param index * @param index The index of the parameter to retrieve.
* The index of the parameter to retrieve.
* @return The parameter. * @return The parameter.
* @see #getParamCount() * @see #getParamCount()
*/ */
public Parameter getParam(int index); public Parameter getParam(int index);
/** /**
* Returns the number of parameters this completion takes. * Returns the number of parameters this completion takes.
* *
@@ -42,82 +41,73 @@ public interface ParameterizedCompletion extends Completion {
* @see #getParam(int) * @see #getParam(int)
*/ */
public int getParamCount(); public int getParamCount();
public ParameterizedCompletionInsertionInfo getInsertionInfo(JTextComponent tc, boolean replaceTabsWithSpaces); public ParameterizedCompletionInsertionInfo getInsertionInfo(JTextComponent tc, boolean replaceTabsWithSpaces);
/** /**
* Returns whether a tool tip displaying assistance for each parameter * Returns whether a tool tip displaying assistance for each parameter while it
* while it is being edited is appropriate for this completion. * is being edited is appropriate for this completion.
* *
* @return Whether the tool tip is appropriate to display. * @return Whether the tool tip is appropriate to display.
*/ */
public boolean getShowParameterToolTip(); public boolean getShowParameterToolTip();
/** /**
* A parameter passed to a parameterized {@link Completion}. * A parameter passed to a parameterized {@link Completion}.
*/ */
public static class Parameter { public static class Parameter {
private String name; private String name;
private Object type; private Object type;
private String desc; private String desc;
private boolean isEndParam; private boolean isEndParam;
/** /**
* Constructor. * Constructor.
* *
* @param type * @param type The type of this parameter. This may be <code>null</code> for
* The type of this parameter. This may be * languages without specific types, dynamic typing, etc. Usually
* <code>null</code> for languages without specific types, * you'll pass a String for this value, but you may pass any object
* dynamic typing, etc. Usually you'll pass a String for this * representing a type in your language, as long as its
* value, but you may pass any object representing a type in * <code>toString()</code> method returns a string representation of
* your language, as long as its <code>toString()</code> * the type.
* method * @param name The name of the parameter.
* returns a string representation of the type.
* @param name
* The name of the parameter.
*/ */
public Parameter(Object type, String name) { public Parameter(Object type, String name) {
this(type, name, false); this(type, name, false);
} }
/** /**
* Constructor. * Constructor.
* *
* @param type * @param type The type of this parameter. This may be <code>null</code> for
* The type of this parameter. This may be * languages without specific types, dynamic typing, etc.
* <code>null</code> for languages without specific types, * Usually you'll pass a String for this value, but you may pass
* dynamic typing, etc. Usually you'll pass a String for this * any object representing a type in your language, as long as
* value, but you may pass any object representing a type in * its <code>toString()</code> method returns a string
* your language, as long as its <code>toString()</code> * representation of the type.
* method * @param name The name of the parameter.
* returns a string representation of the type. * @param endParam Whether this parameter is an "ending parameter;" that is,
* @param name * whether this parameter is at a logical "ending point" in the
* The name of the parameter. * completion text. If the user types in a parameter that is an
* @param endParam * ending point, parameter completion mode terminates. Set this
* Whether this parameter is an "ending parameter;" * to <code>true</code> for a trailing parameter after a
* that is, whether this parameter is at a logical "ending * function call's closing ')', for example.
* point" in the completion text. If the user types in a
* parameter that is an ending point, parameter completion
* mode
* terminates. Set this to <code>true</code> for a trailing
* parameter after a function call's closing ')', for
* example.
*/ */
public Parameter(Object type, String name, boolean endParam) { public Parameter(Object type, String name, boolean endParam) {
this.name = name; this.name = name;
this.type = type; this.type = type;
this.isEndParam = endParam; this.isEndParam = endParam;
} }
public String getDescription() { public String getDescription() {
return desc; return desc;
} }
public String getName() { public String getName() {
return name; return name;
} }
/** /**
* Returns the type of this parameter, as a string. * Returns the type of this parameter, as a string.
* *
@@ -126,7 +116,7 @@ public interface ParameterizedCompletion extends Completion {
public String getType() { public String getType() {
return type == null ? null : type.toString(); return type == null ? null : type.toString();
} }
/** /**
* Returns the object used to describe the type of this parameter. * Returns the object used to describe the type of this parameter.
* *
@@ -135,22 +125,21 @@ public interface ParameterizedCompletion extends Completion {
public Object getTypeObject() { public Object getTypeObject() {
return type; return type;
} }
/** /**
* @return Whether this parameter is an "ending parameter;" * @return Whether this parameter is an "ending parameter;" that is, whether
* that is, whether this parameter is at a logical "ending * this parameter is at a logical "ending point" in the completion text.
* point" in the completion text. If the user types in a * If the user types in a parameter that is an ending point, parameter
* parameter that is an ending point, parameter completion mode * completion mode terminates.
* terminates.
*/ */
public boolean isEndParam() { public boolean isEndParam() {
return isEndParam; return isEndParam;
} }
public void setDescription(String desc) { public void setDescription(String desc) {
this.desc = desc; this.desc = desc;
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -28,17 +28,17 @@ import javax.swing.text.JTextComponent;
import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator; import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator;
/** /**
* A small popup window offering a list of likely choices for a parameter * A small popup window offering a list of likely choices for a parameter when
* when the user has code-completed a parameterized completion. For example, * the user has code-completed a parameterized completion. For example, if they
* if they have just code-completed the C function "<code>fprintf</code>", * have just code-completed the C function "<code>fprintf</code>", when entering
* when entering the file name, this popup might display all local variables * the file name, this popup might display all local variables of type
* of type "<code>char *</code>". * "<code>char *</code>".
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public class ParameterizedCompletionChoicesWindow extends JWindow { public class ParameterizedCompletionChoicesWindow extends JWindow {
/** /**
* The parent AutoCompletion instance. * The parent AutoCompletion instance.
*/ */
@@ -60,22 +60,20 @@ public class ParameterizedCompletionChoicesWindow extends JWindow {
*/ */
private JScrollPane sp; private JScrollPane sp;
/** /**
* Comparator used to sort completions by their relevance before sorting * Comparator used to sort completions by their relevance before sorting them
* them lexicographically. * lexicographically.
*/ */
private static final Comparator<Completion> sortByRelevanceComparator = new SortByRelevanceComparator(); private static final Comparator<Completion> sortByRelevanceComparator = new SortByRelevanceComparator();
/** /**
* Constructor. * Constructor.
* *
* @param parent * @param parent The parent window (hosting the text component).
* The parent window (hosting the text component). * @param ac The auto-completion instance.
* @param ac * @param context The completion context.
* The auto-completion instance.
* @param context
* The completion context.
*/ */
public ParameterizedCompletionChoicesWindow(Window parent, AutoCompletion ac, final ParameterizedCompletionContext context) { public ParameterizedCompletionChoicesWindow(Window parent, AutoCompletion ac,
final ParameterizedCompletionContext context) {
super(parent); super(parent);
this.ac = ac; this.ac = ac;
ComponentOrientation o = ac.getTextComponentOrientation(); ComponentOrientation o = ac.getTextComponentOrientation();
@@ -85,7 +83,7 @@ public class ParameterizedCompletionChoicesWindow extends JWindow {
list.setCellRenderer(ac.getParamChoicesRenderer()); list.setCellRenderer(ac.getParamChoicesRenderer());
} }
list.addMouseListener(new MouseAdapter() { list.addMouseListener(new MouseAdapter() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) { if (e.getClickCount() == 2) {
@@ -103,23 +101,21 @@ public class ParameterizedCompletionChoicesWindow extends JWindow {
decorator.decorate(this); decorator.decorate(this);
} }
} }
/** /**
* Returns the selected value. * Returns the selected value.
* *
* @return The selected value, or <code>null</code> if nothing is * @return The selected value, or <code>null</code> if nothing is selected.
* selected.
*/ */
public String getSelectedChoice() { public String getSelectedChoice() {
Completion c = (Completion) list.getSelectedValue(); Completion c = (Completion) list.getSelectedValue();
return c == null ? null : c.toString(); return c == null ? null : c.toString();
} }
/** /**
* Changes the selected index. * Changes the selected index.
* *
* @param amount * @param amount The amount by which to change the selected index.
* The amount by which to change the selected index.
*/ */
public void incSelection(int amount) { public void incSelection(int amount) {
int selection = list.getSelectedIndex(); int selection = list.getSelectedIndex();
@@ -133,14 +129,12 @@ public class ParameterizedCompletionChoicesWindow extends JWindow {
list.setSelectedIndex(selection); list.setSelectedIndex(selection);
list.ensureIndexIsVisible(selection); list.ensureIndexIsVisible(selection);
} }
/** /**
* Initializes this window to offer suggestions for the parameters of * Initializes this window to offer suggestions for the parameters of a specific
* a specific completion. * completion.
* *
* @param pc * @param pc The completion whose parameters we should offer suggestions for.
* The completion whose parameters we should offer suggestions
* for.
*/ */
public void initialize(ParameterizedCompletion pc) { public void initialize(ParameterizedCompletion pc) {
CompletionProvider provider = pc.getProvider(); CompletionProvider provider = pc.getProvider();
@@ -158,12 +152,11 @@ public class ParameterizedCompletionChoicesWindow extends JWindow {
choicesListList.add(choices); choicesListList.add(choices);
} }
} }
/** /**
* Sets the location of this window relative to the given rectangle. * Sets the location of this window relative to the given rectangle.
* *
* @param r * @param r The visual position of the caret (in screen coordinates).
* The visual position of the caret (in screen coordinates).
*/ */
public void setLocationRelativeTo(Rectangle r) { public void setLocationRelativeTo(Rectangle r) {
// Multi-monitor support - make sure the completion window (and // Multi-monitor support - make sure the completion window (and
@@ -187,18 +180,16 @@ public class ParameterizedCompletionChoicesWindow extends JWindow {
} }
setLocation(x, y); setLocation(x, y);
} }
/** /**
* Displays the choices for the specified parameter matching the given * Displays the choices for the specified parameter matching the given text.
* text. This will display or hide this popup window as necessary. * This will display or hide this popup window as necessary.
* *
* @param param * @param param The index of the parameter the caret is currently in. This may
* The index of the parameter the caret is currently in. * be <code>-1</code> if not in a parameter (i.e., on the comma
* This may be <code>-1</code> if not in a parameter (i.e., on * between parameters).
* the comma between parameters). * @param prefix Text in the parameter before the dot. This may be
* @param prefix * <code>null</code> to represent the empty string.
* Text in the parameter before the dot. This may
* be <code>null</code> to represent the empty string.
*/ */
public void setParameter(int param, String prefix) { public void setParameter(int param, String prefix) {
model.clear(); model.clear();
@@ -250,12 +241,11 @@ public class ParameterizedCompletionChoicesWindow extends JWindow {
setVisible(false); setVisible(false);
} }
} }
/** /**
* Toggles the visibility of this popup window. * Toggles the visibility of this popup window.
* *
* @param visible * @param visible Whether this window should be visible.
* Whether this window should be visible.
*/ */
@Override @Override
public void setVisible(boolean visible) { public void setVisible(boolean visible) {
@@ -268,7 +258,7 @@ public class ParameterizedCompletionChoicesWindow extends JWindow {
super.setVisible(visible); super.setVisible(visible);
} }
} }
/** /**
* Updates the <tt>LookAndFeel</tt> of this window. * Updates the <tt>LookAndFeel</tt> of this window.
*/ */
@@ -48,8 +48,8 @@ import org.fife.ui.rtextarea.ChangeableHighlightPainter;
/** /**
* Manages UI and state specific to parameterized completions - the parameter * Manages UI and state specific to parameterized completions - the parameter
* description tool tip, the parameter completion choices list, the actual * description tool tip, the parameter completion choices list, the actual
* highlights in the editor, etc. This component installs new key bindings * highlights in the editor, etc. This component installs new key bindings when
* when appropriate to allow the user to cycle through the parameters of the * appropriate to allow the user to cycle through the parameters of the
* completion, and optionally cycle through completion choices for those * completion, and optionally cycle through completion choices for those
* parameters. * parameters.
* *
@@ -57,7 +57,7 @@ import org.fife.ui.rtextarea.ChangeableHighlightPainter;
* @version 1.0 * @version 1.0
*/ */
class ParameterizedCompletionContext { class ParameterizedCompletionContext {
/** /**
* The parent window. * The parent window.
*/ */
@@ -95,13 +95,13 @@ class ParameterizedCompletionContext {
*/ */
private Listener listener; private Listener listener;
/** /**
* The minimum offset into the document that the caret can move to * The minimum offset into the document that the caret can move to before this
* before this tool tip disappears. * tool tip disappears.
*/ */
private int minPos; private int minPos;
/** /**
* The maximum offset into the document that the caret can move to * The maximum offset into the document that the caret can move to before this
* before this tool tip disappears. * tool tip disappears.
*/ */
private Position maxPos; // Moves with text inserted. private Position maxPos; // Moves with text inserted.
private Position defaultEndOffs; private Position defaultEndOffs;
@@ -140,7 +140,7 @@ class ParameterizedCompletionContext {
private static final String IM_KEY_ESCAPE = "ParamCompKey.Escape"; private static final String IM_KEY_ESCAPE = "ParamCompKey.Escape";
private static final String IM_KEY_ENTER = "ParamCompKey.Enter"; private static final String IM_KEY_ENTER = "ParamCompKey.Enter";
private static final String IM_KEY_CLOSING = "ParamCompKey.Closing"; private static final String IM_KEY_CLOSING = "ParamCompKey.Closing";
/** /**
* Constructor. * Constructor.
*/ */
@@ -156,7 +156,7 @@ class ParameterizedCompletionContext {
tags = new ArrayList<Object>(1); // Usually small tags = new ArrayList<Object>(1); // Usually small
paramCopyInfos = new ArrayList<ParamCopyInfo>(1); paramCopyInfos = new ArrayList<ParamCopyInfo>(1);
} }
/** /**
* Activates parameter completion support. * Activates parameter completion support.
* *
@@ -195,7 +195,7 @@ class ParameterizedCompletionContext {
prepareParamChoicesWindow(); prepareParamChoicesWindow();
paramChoicesWindow.setVisible(true); paramChoicesWindow.setVisible(true);
} }
/** /**
* Creates the completion window offering suggestions for parameters. * Creates the completion window offering suggestions for parameters.
* *
@@ -206,10 +206,9 @@ class ParameterizedCompletionContext {
pcw.initialize(pc); pcw.initialize(pc);
return pcw; return pcw;
} }
/** /**
* Hides any popup windows and terminates parameterized completion * Hides any popup windows and terminates parameterized completion assistance.
* assistance.
* *
* @see #activate() * @see #activate()
*/ */
@@ -226,15 +225,13 @@ class ParameterizedCompletionContext {
paramChoicesWindow.setVisible(false); paramChoicesWindow.setVisible(false);
} }
} }
/** /**
* Returns the text inserted for the parameter containing the specified * Returns the text inserted for the parameter containing the specified offset.
* offset.
* *
* @param offs * @param offs The offset into the document.
* The offset into the document. * @return The text of the parameter containing the offset, or <code>null</code>
* @return The text of the parameter containing the offset, or * if the offset is not in a parameter.
* <code>null</code> if the offset is not in a parameter.
*/ */
public String getArgumentText(int offs) { public String getArgumentText(int offs) {
List<Highlight> paramHighlights = getParameterHighlights(); List<Highlight> paramHighlights = getParameterHighlights();
@@ -258,12 +255,12 @@ class ParameterizedCompletionContext {
} }
return null; return null;
} }
/** /**
* Returns the highlight of the current parameter. * Returns the highlight of the current parameter.
* *
* @return The current parameter's highlight, or <code>null</code> if * @return The current parameter's highlight, or <code>null</code> if the caret
* the caret is not in a parameter's bounds. * is not in a parameter's bounds.
* @see #getCurrentParameterStartOffset() * @see #getCurrentParameterStartOffset()
*/ */
private Highlight getCurrentParameterHighlight() { private Highlight getCurrentParameterHighlight() {
@@ -280,7 +277,7 @@ class ParameterizedCompletionContext {
} }
return null; return null;
} }
private int getCurrentParameterIndex() { private int getCurrentParameterIndex() {
JTextComponent tc = ac.getTextComponent(); JTextComponent tc = ac.getTextComponent();
int dot = tc.getCaretPosition(); int dot = tc.getCaretPosition();
@@ -296,27 +293,26 @@ class ParameterizedCompletionContext {
} }
return -1; return -1;
} }
/** /**
* Returns the starting offset of the current parameter. * Returns the starting offset of the current parameter.
* *
* @return The current parameter's starting offset, or <code>-1</code> if * @return The current parameter's starting offset, or <code>-1</code> if the
* the caret is not in a parameter's bounds. * caret is not in a parameter's bounds.
* @see #getCurrentParameterHighlight() * @see #getCurrentParameterHighlight()
*/ */
private int getCurrentParameterStartOffset() { private int getCurrentParameterStartOffset() {
Highlight h = getCurrentParameterHighlight(); Highlight h = getCurrentParameterHighlight();
return h != null ? h.getStartOffset() + 1 : -1; return h != null ? h.getStartOffset() + 1 : -1;
} }
/** /**
* Returns the highlight from a list that comes "first" in a list. Even * Returns the highlight from a list that comes "first" in a list. Even though
* though most parameter highlights are ordered, sometimes they aren't * most parameter highlights are ordered, sometimes they aren't (e.g. the
* (e.g. the "cursor" parameter in a template completion is always last, * "cursor" parameter in a template completion is always last, even though it
* even though it can be anywhere in the template). * can be anywhere in the template).
* *
* @param highlights * @param highlights The list of highlights. Assumed to be non-empty.
* The list of highlights. Assumed to be non-empty.
* @return The highlight that comes first in the document. * @return The highlight that comes first in the document.
* @see #getLastHighlight(List) * @see #getLastHighlight(List)
*/ */
@@ -332,15 +328,14 @@ class ParameterizedCompletionContext {
} }
return first; return first;
} }
/** /**
* Returns the highlight from a list that comes "last" in that list. Even * Returns the highlight from a list that comes "last" in that list. Even though
* though most parameter highlights are ordered, sometimes they aren't * most parameter highlights are ordered, sometimes they aren't (e.g. the
* (e.g. the "cursor" parameter in a template completion is always last, * "cursor" parameter in a template completion is always last, even though it
* even though it can be anywhere in the template. * can be anywhere in the template.
* *
* @param highlights * @param highlights The list of highlights. Assumed to be non-empty.
* The list of highlights. Assumed to be non-empty.
* @return The highlight that comes last in the document. * @return The highlight that comes last in the document.
* @see #getFirstHighlight(List) * @see #getFirstHighlight(List)
*/ */
@@ -356,7 +351,7 @@ class ParameterizedCompletionContext {
} }
return last; return last;
} }
public List<Highlight> getParameterHighlights() { public List<Highlight> getParameterHighlights() {
List<Highlight> paramHighlights = new ArrayList<Highlight>(2); List<Highlight> paramHighlights = new ArrayList<Highlight>(2);
JTextComponent tc = ac.getTextComponent(); JTextComponent tc = ac.getTextComponent();
@@ -369,12 +364,12 @@ class ParameterizedCompletionContext {
} }
return paramHighlights; return paramHighlights;
} }
/** /**
* Inserts the choice selected in the parameter choices window. * Inserts the choice selected in the parameter choices window.
* *
* @return Whether the choice was inserted. This will be <code>false</code> * @return Whether the choice was inserted. This will be <code>false</code> if
* if the window is not visible, or no choice is selected. * the window is not visible, or no choice is selected.
*/ */
boolean insertSelectedChoice() { boolean insertSelectedChoice() {
if (paramChoicesWindow != null && paramChoicesWindow.isVisible()) { if (paramChoicesWindow != null && paramChoicesWindow.isVisible()) {
@@ -396,10 +391,10 @@ class ParameterizedCompletionContext {
} }
return false; return false;
} }
/** /**
* Installs key bindings on the text component that facilitate the user * Installs key bindings on the text component that facilitate the user editing
* editing this completion's parameters. * this completion's parameters.
* *
* @see #uninstallKeyBindings() * @see #uninstallKeyBindings()
*/ */
@@ -447,7 +442,7 @@ class ParameterizedCompletionContext {
oldClosingAction = am.get(IM_KEY_CLOSING); oldClosingAction = am.get(IM_KEY_CLOSING);
am.put(IM_KEY_CLOSING, new ClosingAction()); am.put(IM_KEY_CLOSING, new ClosingAction());
} }
/** /**
* Moves to and selects the next parameter. * Moves to and selects the next parameter.
* *
@@ -486,7 +481,7 @@ class ParameterizedCompletionContext {
tc.setSelectionEnd(currentNext.getEndOffset()); tc.setSelectionEnd(currentNext.getEndOffset());
updateToolTipText(pos); updateToolTipText(pos);
} }
/** /**
* Moves to and selects the previous parameter. * Moves to and selects the previous parameter.
* *
@@ -507,8 +502,8 @@ class ParameterizedCompletionContext {
List<Highlight> highlights = getParameterHighlights(); List<Highlight> highlights = getParameterHighlights();
for (int i = 0; i < highlights.size(); i++) { for (int i = 0; i < highlights.size(); i++) {
Highlight h = highlights.get(i); Highlight h = highlights.get(i);
if (currentPrev == null || currentPrev.getStartOffset() >= dot if (currentPrev == null || currentPrev.getStartOffset() >= dot || (h.getStartOffset() < selStart
|| (h.getStartOffset() < selStart && (h.getStartOffset() > currentPrev.getStartOffset() || pos == lastSelectedParam))) { && (h.getStartOffset() > currentPrev.getStartOffset() || pos == lastSelectedParam))) {
currentPrev = h; currentPrev = h;
pos = i; pos = i;
} }
@@ -533,7 +528,7 @@ class ParameterizedCompletionContext {
deactivate(); deactivate();
} }
} }
private void possiblyUpdateParamCopies(Document doc) { private void possiblyUpdateParamCopies(Document doc) {
int index = getCurrentParameterIndex(); int index = getCurrentParameterIndex();
// FunctionCompletions add an extra param at end of inserted text // FunctionCompletions add an extra param at end of inserted text
@@ -567,7 +562,7 @@ class ParameterizedCompletionContext {
deactivate(); deactivate();
} }
} }
/** /**
* Updates the optional window listing likely completion choices, * Updates the optional window listing likely completion choices,
*/ */
@@ -595,7 +590,7 @@ class ParameterizedCompletionContext {
paramChoicesWindow.setParameter(lastSelectedParam, paramPrefix); paramChoicesWindow.setParameter(lastSelectedParam, paramPrefix);
} }
} }
/** /**
* Removes the bounding boxes around parameters. * Removes the bounding boxes around parameters.
*/ */
@@ -611,19 +606,16 @@ class ParameterizedCompletionContext {
} }
paramCopyInfos.clear(); paramCopyInfos.clear();
} }
/** /**
* Replaces highlighted text with new text. Takes special care so that * Replaces highlighted text with new text. Takes special care so that the
* the highlight stays just around the newly-highlighted text, since * highlight stays just around the newly-highlighted text, since Swing's
* Swing's <code>Highlight</code> classes are funny about insertions at * <code>Highlight</code> classes are funny about insertions at their start
* their start offsets. * offsets.
* *
* @param doc * @param doc The document.
* The document. * @param h The highlight whose text to change.
* @param h * @param replacement The new text to be in the highlight.
* The highlight whose text to change.
* @param replacement
* The new text to be in the highlight.
* @return The replacement highlight for <code>h</code>. * @return The replacement highlight for <code>h</code>.
*/ */
private Highlight replaceHighlightedText(Document doc, Highlight h, String replacement) { private Highlight replaceHighlightedText(Document doc, Highlight h, String replacement) {
@@ -646,7 +638,7 @@ class ParameterizedCompletionContext {
} }
return null; return null;
} }
/** /**
* Removes the key bindings we installed. * Removes the key bindings we installed.
* *
@@ -682,11 +674,10 @@ class ParameterizedCompletionContext {
im.put(ks, oldClosingKey); im.put(ks, oldClosingKey);
am.put(IM_KEY_CLOSING, oldClosingAction); am.put(IM_KEY_CLOSING, oldClosingAction);
} }
/** /**
* Updates the text in the tool tip to have the current parameter * Updates the text in the tool tip to have the current parameter displayed in
* displayed in bold. The "current parameter" is determined from the * bold. The "current parameter" is determined from the current caret position.
* current caret position.
* *
* @return The "prefix" of text in the caret's parameter before the caret. * @return The "prefix" of text in the caret's parameter before the caret.
*/ */
@@ -718,7 +709,7 @@ class ParameterizedCompletionContext {
updateToolTipText(index); updateToolTipText(index);
return paramPrefix; return paramPrefix;
} }
private void updateToolTipText(int selectedParam) { private void updateToolTipText(int selectedParam) {
if (selectedParam != lastSelectedParam) { if (selectedParam != lastSelectedParam) {
if (tip != null) { if (tip != null) {
@@ -727,7 +718,7 @@ class ParameterizedCompletionContext {
this.lastSelectedParam = selectedParam; this.lastSelectedParam = selectedParam;
} }
} }
/** /**
* Updates the <code>LookAndFeel</code> of all popup windows this context * Updates the <code>LookAndFeel</code> of all popup windows this context
* manages. * manages.
@@ -740,12 +731,12 @@ class ParameterizedCompletionContext {
paramChoicesWindow.updateUI(); paramChoicesWindow.updateUI();
} }
} }
/** /**
* Called when the user presses Enter while entering parameters. * Called when the user presses Enter while entering parameters.
*/ */
private class GotoEndAction extends AbstractAction { private class GotoEndAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// If the param choices window is visible and something is chosen, // If the param choices window is visible and something is chosen,
@@ -771,19 +762,19 @@ class ParameterizedCompletionContext {
} }
} }
} }
private Action getDefaultEnterAction(JTextComponent tc) { private Action getDefaultEnterAction(JTextComponent tc) {
ActionMap am = tc.getActionMap(); ActionMap am = tc.getActionMap();
return am.get(DefaultEditorKit.insertBreakAction); return am.get(DefaultEditorKit.insertBreakAction);
} }
} }
/** /**
* Called when the user types the character marking the closing of the * Called when the user types the character marking the closing of the parameter
* parameter list, such as '<code>)</code>'. * list, such as '<code>)</code>'.
*/ */
private class ClosingAction extends AbstractAction { private class ClosingAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
JTextComponent tc = ac.getTextComponent(); JTextComponent tc = ac.getTextComponent();
@@ -812,7 +803,7 @@ class ParameterizedCompletionContext {
tc.replaceSelection(Character.toString(end)); tc.replaceSelection(Character.toString(end));
} }
} }
public int getCount(String text, char ch) { public int getCount(String text, char ch) {
int count = 0; int count = 0;
int old = 0; int old = 0;
@@ -824,12 +815,12 @@ class ParameterizedCompletionContext {
return count; return count;
} }
} }
/** /**
* Action performed when the user hits the escape key. * Action performed when the user hits the escape key.
*/ */
private class HideAction extends AbstractAction { private class HideAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// On first escape press, if the param choices window is visible, // On first escape press, if the param choices window is visible,
@@ -844,20 +835,19 @@ class ParameterizedCompletionContext {
} }
} }
} }
/** /**
* Listens for various events in the text component while this tool tip * Listens for various events in the text component while this tool tip is
* is visible. * visible.
*/ */
private class Listener implements FocusListener, CaretListener, DocumentListener { private class Listener implements FocusListener, CaretListener, DocumentListener {
private boolean markOccurrencesEnabled; private boolean markOccurrencesEnabled;
/** /**
* Called when the text component's caret moves. * Called when the text component's caret moves.
* *
* @param e * @param e The event.
* The event.
*/ */
@Override @Override
public void caretUpdate(CaretEvent e) { public void caretUpdate(CaretEvent e) {
@@ -875,37 +865,36 @@ class ParameterizedCompletionContext {
prepareParamChoicesWindow(); prepareParamChoicesWindow();
} }
} }
@Override @Override
public void changedUpdate(DocumentEvent e) {} public void changedUpdate(DocumentEvent e) {
}
/** /**
* Called when the text component gains focus. * Called when the text component gains focus.
* *
* @param e * @param e The event.
* The event.
*/ */
@Override @Override
public void focusGained(FocusEvent e) { public void focusGained(FocusEvent e) {
// Do nothing // Do nothing
} }
/** /**
* Called when the text component loses focus. * Called when the text component loses focus.
* *
* @param e * @param e The event.
* The event.
*/ */
@Override @Override
public void focusLost(FocusEvent e) { public void focusLost(FocusEvent e) {
deactivate(); deactivate();
} }
private void handleDocumentEvent(final DocumentEvent e) { private void handleDocumentEvent(final DocumentEvent e) {
if (!ignoringDocumentEvents) { if (!ignoringDocumentEvents) {
ignoringDocumentEvents = true; ignoringDocumentEvents = true;
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
possiblyUpdateParamCopies(e.getDocument()); possiblyUpdateParamCopies(e.getDocument());
@@ -914,17 +903,16 @@ class ParameterizedCompletionContext {
}); });
} }
} }
@Override @Override
public void insertUpdate(DocumentEvent e) { public void insertUpdate(DocumentEvent e) {
handleDocumentEvent(e); handleDocumentEvent(e);
} }
/** /**
* Installs this listener onto a text component. * Installs this listener onto a text component.
* *
* @param tc * @param tc The text component to install onto.
* The text component to install onto.
* @see #uninstall() * @see #uninstall()
*/ */
public void install(JTextComponent tc) { public void install(JTextComponent tc) {
@@ -950,7 +938,8 @@ class ParameterizedCompletionContext {
} }
for (int i = 0; i < info.getReplacementCopyCount(); i++) { for (int i = 0; i < info.getReplacementCopyCount(); i++) {
ReplacementCopy rc = info.getReplacementCopy(i); ReplacementCopy rc = info.getReplacementCopy(i);
paramCopyInfos.add(new ParamCopyInfo(rc.getId(), (Highlight) h.addHighlight(rc.getStart(), rc.getEnd(), paramCopyP))); paramCopyInfos.add(new ParamCopyInfo(rc.getId(),
(Highlight) h.addHighlight(rc.getStart(), rc.getEnd(), paramCopyP)));
} }
// Go back and start at the first parameter. // Go back and start at the first parameter.
tc.setCaretPosition(info.getSelectionStart()); tc.setCaretPosition(info.getSelectionStart());
@@ -981,12 +970,12 @@ class ParameterizedCompletionContext {
tc.addFocusListener(this); tc.addFocusListener(this);
installKeyBindings(); installKeyBindings();
} }
@Override @Override
public void removeUpdate(DocumentEvent e) { public void removeUpdate(DocumentEvent e) {
handleDocumentEvent(e); handleDocumentEvent(e);
} }
/** /**
* Uninstalls this listener from the current text component. * Uninstalls this listener from the current text component.
*/ */
@@ -1005,21 +994,21 @@ class ParameterizedCompletionContext {
removeParameterHighlights(); removeParameterHighlights();
} }
} }
/** /**
* Action performed when the user presses the up or down arrow keys and * Action performed when the user presses the up or down arrow keys and the
* the parameter completion choices popup is visible. * parameter completion choices popup is visible.
*/ */
private class NextChoiceAction extends AbstractAction { private class NextChoiceAction extends AbstractAction {
private Action oldAction; private Action oldAction;
private int amount; private int amount;
public NextChoiceAction(int amount, Action oldAction) { public NextChoiceAction(int amount, Action oldAction) {
this.amount = amount; this.amount = amount;
this.oldAction = oldAction; this.oldAction = oldAction;
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (paramChoicesWindow != null && paramChoicesWindow.isVisible()) { if (paramChoicesWindow != null && paramChoicesWindow.isVisible()) {
@@ -1031,34 +1020,34 @@ class ParameterizedCompletionContext {
} }
} }
} }
/** /**
* Action performed when the user hits the tab key. * Action performed when the user hits the tab key.
*/ */
private class NextParamAction extends AbstractAction { private class NextParamAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
moveToNextParam(); moveToNextParam();
} }
} }
private static class ParamCopyInfo { private static class ParamCopyInfo {
private String paramName; private String paramName;
private Highlight h; private Highlight h;
public ParamCopyInfo(String paramName, Highlight h) { public ParamCopyInfo(String paramName, Highlight h) {
this.paramName = paramName; this.paramName = paramName;
this.h = h; this.h = h;
} }
} }
/** /**
* Action performed when the user hits shift+tab. * Action performed when the user hits shift+tab.
*/ */
private class PrevParamAction extends AbstractAction { private class PrevParamAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
moveToPreviousParam(); moveToPreviousParam();
@@ -28,7 +28,7 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
* @version 1.0 * @version 1.0
*/ */
class ParameterizedCompletionDescriptionToolTip { class ParameterizedCompletionDescriptionToolTip {
/** /**
* The actual tool tip. * The actual tool tip.
*/ */
@@ -41,23 +41,21 @@ class ParameterizedCompletionDescriptionToolTip {
* The completion being described. * The completion being described.
*/ */
private ParameterizedCompletion pc; private ParameterizedCompletion pc;
/** /**
* Constructor. * Constructor.
* *
* @param owner * @param owner The parent window.
* The parent window. * @param ac The parent auto-completion.
* @param ac * @param pc The completion being described.
* The parent auto-completion.
* @param pc
* The completion being described.
*/ */
public ParameterizedCompletionDescriptionToolTip(Window owner, ParameterizedCompletionContext context, AutoCompletion ac, public ParameterizedCompletionDescriptionToolTip(Window owner, ParameterizedCompletionContext context,
ParameterizedCompletion pc) { AutoCompletion ac, ParameterizedCompletion pc) {
tooltip = new JWindow(owner); tooltip = new JWindow(owner);
this.pc = pc; this.pc = pc;
descLabel = new JLabel(); descLabel = new JLabel();
descLabel.setBorder(BorderFactory.createCompoundBorder(TipUtil.getToolTipBorder(), BorderFactory.createEmptyBorder(2, 5, 2, 5))); descLabel.setBorder(BorderFactory.createCompoundBorder(TipUtil.getToolTipBorder(),
BorderFactory.createEmptyBorder(2, 5, 2, 5)));
descLabel.setOpaque(true); descLabel.setOpaque(true);
descLabel.setBackground(TipUtil.getToolTipBackground()); descLabel.setBackground(TipUtil.getToolTipBackground());
// It appears that if a JLabel is set as a content pane directly, when // It appears that if a JLabel is set as a content pane directly, when
@@ -77,7 +75,7 @@ class ParameterizedCompletionDescriptionToolTip {
updateText(0); updateText(0);
tooltip.setFocusableWindowState(false); tooltip.setFocusableWindowState(false);
} }
/** /**
* Returns whether this tool tip is visible. * Returns whether this tool tip is visible.
* *
@@ -87,12 +85,11 @@ class ParameterizedCompletionDescriptionToolTip {
public boolean isVisible() { public boolean isVisible() {
return tooltip.isVisible(); return tooltip.isVisible();
} }
/** /**
* Sets the location of this tool tip relative to the given rectangle. * Sets the location of this tool tip relative to the given rectangle.
* *
* @param r * @param r The visual position of the caret (in screen coordinates).
* The visual position of the caret (in screen coordinates).
*/ */
public void setLocationRelativeTo(Rectangle r) { public void setLocationRelativeTo(Rectangle r) {
// Multi-monitor support - make sure the completion window (and // Multi-monitor support - make sure the completion window (and
@@ -119,24 +116,22 @@ class ParameterizedCompletionDescriptionToolTip {
} }
tooltip.setLocation(x, y); tooltip.setLocation(x, y);
} }
/** /**
* Toggles the visibility of this tool tip. * Toggles the visibility of this tool tip.
* *
* @param visible * @param visible Whether this tool tip should be visible.
* Whether this tool tip should be visible.
* @see #isVisible() * @see #isVisible()
*/ */
public void setVisible(boolean visible) { public void setVisible(boolean visible) {
tooltip.setVisible(visible); tooltip.setVisible(visible);
} }
/** /**
* Updates the text in the tool tip to have the current parameter * Updates the text in the tool tip to have the current parameter displayed in
* displayed in bold. * bold.
* *
* @param selectedParam * @param selectedParam The index of the selected parameter.
* The index of the selected parameter.
* @return Whether the text needed to be updated. * @return Whether the text needed to be updated.
*/ */
public boolean updateText(int selectedParam) { public boolean updateText(int selectedParam) {
@@ -170,10 +165,9 @@ class ParameterizedCompletionDescriptionToolTip {
tooltip.pack(); tooltip.pack();
return true; return true;
} }
/** /**
* Updates the <tt>LookAndFeel</tt> of this window and the description * Updates the <tt>LookAndFeel</tt> of this window and the description window.
* window.
*/ */
public void updateUI() { public void updateUI() {
SwingUtilities.updateComponentTreeUI(tooltip); SwingUtilities.updateComponentTreeUI(tooltip);
@@ -22,7 +22,7 @@ import org.fife.ui.rsyntaxtextarea.DocumentRange;
* @version 1.0 * @version 1.0
*/ */
class ParameterizedCompletionInsertionInfo { class ParameterizedCompletionInsertionInfo {
private int minOffs; private int minOffs;
private Position maxOffs; private Position maxOffs;
private int defaultEnd; private int defaultEnd;
@@ -31,26 +31,24 @@ class ParameterizedCompletionInsertionInfo {
private String textToInsert; private String textToInsert;
private List<DocumentRange> replacementLocations; private List<DocumentRange> replacementLocations;
private List<ReplacementCopy> replacementCopies; private List<ReplacementCopy> replacementCopies;
public ParameterizedCompletionInsertionInfo() { public ParameterizedCompletionInsertionInfo() {
defaultEnd = -1; defaultEnd = -1;
} }
public void addReplacementCopy(String id, int start, int end) { public void addReplacementCopy(String id, int start, int end) {
if (replacementCopies == null) { if (replacementCopies == null) {
replacementCopies = new ArrayList<ReplacementCopy>(1); replacementCopies = new ArrayList<ReplacementCopy>(1);
} }
replacementCopies.add(new ReplacementCopy(id, start, end)); replacementCopies.add(new ReplacementCopy(id, start, end));
} }
/** /**
* Marks a region of the replacement text as representing a variable name * Marks a region of the replacement text as representing a variable name or
* or some other construct that the user should replace. * some other construct that the user should replace.
* *
* @param start * @param start The start offset.
* The start offset. * @param end The end offset.
* @param end
* The end offset.
* @see #getReplacementCount() * @see #getReplacementCount()
* @see #getReplacementLocation(int) * @see #getReplacementLocation(int)
*/ */
@@ -60,14 +58,14 @@ class ParameterizedCompletionInsertionInfo {
} }
replacementLocations.add(new DocumentRange(start, end)); replacementLocations.add(new DocumentRange(start, end));
} }
public int getDefaultEndOffs() { public int getDefaultEndOffs() {
return defaultEnd > -1 ? defaultEnd : getMaxOffset().getOffset(); return defaultEnd > -1 ? defaultEnd : getMaxOffset().getOffset();
} }
/** /**
* Returns the maximum offset the caret can move to before being outside * Returns the maximum offset the caret can move to before being outside of the
* of the text inserted for this completion. * text inserted for this completion.
* *
* @return The maximum offset. * @return The maximum offset.
* @see #getMinOffset() * @see #getMinOffset()
@@ -75,10 +73,10 @@ class ParameterizedCompletionInsertionInfo {
public Position getMaxOffset() { public Position getMaxOffset() {
return maxOffs; return maxOffs;
} }
/** /**
* Returns the minimum offset the caret can move to before being outside * Returns the minimum offset the caret can move to before being outside of the
* of the text inserted for this completion. * text inserted for this completion.
* *
* @return The minimum offset. * @return The minimum offset.
* @see #getMaxOffset() * @see #getMaxOffset()
@@ -86,11 +84,11 @@ class ParameterizedCompletionInsertionInfo {
public int getMinOffset() { public int getMinOffset() {
return minOffs; return minOffs;
} }
public int getReplacementCopyCount() { public int getReplacementCopyCount() {
return replacementCopies == null ? 0 : replacementCopies.size(); return replacementCopies == null ? 0 : replacementCopies.size();
} }
/** /**
* Returns the number of replacements in the completion. * Returns the number of replacements in the completion.
* *
@@ -99,28 +97,27 @@ class ParameterizedCompletionInsertionInfo {
public int getReplacementCount() { public int getReplacementCount() {
return replacementLocations == null ? 0 : replacementLocations.size(); return replacementLocations == null ? 0 : replacementLocations.size();
} }
public ReplacementCopy getReplacementCopy(int index) { public ReplacementCopy getReplacementCopy(int index) {
return replacementCopies.get(index); return replacementCopies.get(index);
} }
/** /**
* Returns the starting- and ending-offsets of the replacement regions * Returns the starting- and ending-offsets of the replacement regions in the
* in the completion. * completion.
* *
* @param index * @param index The replacement region.
* The replacement region.
* @return The range in the document of that replacement region. * @return The range in the document of that replacement region.
* @see #getReplacementCount() * @see #getReplacementCount()
*/ */
public DocumentRange getReplacementLocation(int index) { public DocumentRange getReplacementLocation(int index) {
return replacementLocations.get(index); return replacementLocations.get(index);
} }
/** /**
* Returns the offset that should be the end of the initially selected * Returns the offset that should be the end of the initially selected text when
* text when the completion is inserted (i.e., the end offset of the first * the completion is inserted (i.e., the end offset of the first replacement
* replacement region). * region).
* *
* @return The end offset for the initial selection. * @return The end offset for the initial selection.
* @see #getSelectionStart() * @see #getSelectionStart()
@@ -128,11 +125,11 @@ class ParameterizedCompletionInsertionInfo {
public int getSelectionEnd() { public int getSelectionEnd() {
return selEnd; return selEnd;
} }
/** /**
* Returns the offset that should be the start of the initially selected * Returns the offset that should be the start of the initially selected text
* text when the completion is inserted (i.e., the start offset of the * when the completion is inserted (i.e., the start offset of the first
* first replacement region). * replacement region).
* *
* @return The start offset for the initial selection. * @return The start offset for the initial selection.
* @see #getSelectionEnd() * @see #getSelectionEnd()
@@ -140,7 +137,7 @@ class ParameterizedCompletionInsertionInfo {
public int getSelectionStart() { public int getSelectionStart() {
return selStart; return selStart;
} }
/** /**
* Returns the actual text to insert when the completion is selected. * Returns the actual text to insert when the completion is selected.
* *
@@ -150,24 +147,22 @@ class ParameterizedCompletionInsertionInfo {
public String getTextToInsert() { public String getTextToInsert() {
return textToInsert; return textToInsert;
} }
/** /**
* Returns whether or not there is an initial selected region for the * Returns whether or not there is an initial selected region for the completion
* completion (i.e., whether the completion actually has any parameters). * (i.e., whether the completion actually has any parameters).
* *
* @return Whether there is a region to initially select for the completion. * @return Whether there is a region to initially select for the completion.
*/ */
public boolean hasSelection() { public boolean hasSelection() {
return selEnd != selStart; return selEnd != selStart;
} }
/** /**
* Sets the initially selected region for the completion. * Sets the initially selected region for the completion.
* *
* @param selStart * @param selStart The selection start.
* The selection start. * @param selEnd The selection end.
* @param selEnd
* The selection end.
* @see #getSelectionEnd() * @see #getSelectionEnd()
* @see #getSelectionStart() * @see #getSelectionStart()
*/ */
@@ -175,16 +170,14 @@ class ParameterizedCompletionInsertionInfo {
this.selStart = selStart; this.selStart = selStart;
this.selEnd = selEnd; this.selEnd = selEnd;
} }
/** /**
* Sets the document range the caret can move around in before being * Sets the document range the caret can move around in before being outside of
* outside of the text inserted for the completion. * the text inserted for the completion.
* *
* @param minOffs * @param minOffs The minimum offset.
* The minimum offset. * @param maxOffs The maximum offset, that will track its location as the
* @param maxOffs * document is modified.
* The maximum offset, that will track its location as the
* document is modified.
* @see #getMinOffset() * @see #getMinOffset()
* @see #getMaxOffset() * @see #getMaxOffset()
*/ */
@@ -192,42 +185,41 @@ class ParameterizedCompletionInsertionInfo {
this.minOffs = minOffs; this.minOffs = minOffs;
this.maxOffs = maxOffs; this.maxOffs = maxOffs;
} }
public void setDefaultEndOffs(int end) { public void setDefaultEndOffs(int end) {
defaultEnd = end; defaultEnd = end;
} }
/** /**
* Sets the text to insert for the completion. * Sets the text to insert for the completion.
* *
* @param text * @param text The text to insert.
* The text to insert.
* @see #getTextToInsert() * @see #getTextToInsert()
*/ */
public void setTextToInsert(String text) { public void setTextToInsert(String text) {
this.textToInsert = text; this.textToInsert = text;
} }
public static class ReplacementCopy { public static class ReplacementCopy {
private String id; private String id;
private int start; private int start;
private int end; private int end;
public ReplacementCopy(String id, int start, int end) { public ReplacementCopy(String id, int start, int end) {
this.id = id; this.id = id;
this.start = start; this.start = start;
this.end = end; this.end = end;
} }
public int getEnd() { public int getEnd() {
return end; return end;
} }
public String getId() { public String getId() {
return id; return id;
} }
public int getStart() { public int getStart() {
return start; return start;
} }
@@ -14,8 +14,8 @@ import javax.swing.Action;
/** /**
* An <code>AutoCompletion</code> that adds the ability to cycle through a set * An <code>AutoCompletion</code> that adds the ability to cycle through a set
* of <code>CompletionProvider</code>s via the trigger key. This allows the * of <code>CompletionProvider</code>s via the trigger key. This allows the
* application to logically "group together" completions of similar kinds; * application to logically "group together" completions of similar kinds; for
* for example, Java code completions vs. template completions. * example, Java code completions vs. template completions.
* <p> * <p>
* *
* Usage: * Usage:
@@ -33,15 +33,14 @@ import javax.swing.Action;
* @author mschlegel * @author mschlegel
*/ */
public class RoundRobinAutoCompletion extends AutoCompletion { public class RoundRobinAutoCompletion extends AutoCompletion {
/** The List of CompletionProviders to use */ /** The List of CompletionProviders to use */
private List<CompletionProvider> cycle = new ArrayList<CompletionProvider>(); private List<CompletionProvider> cycle = new ArrayList<CompletionProvider>();
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider A single completion provider.
* A single completion provider.
* @see #addCompletionProvider(CompletionProvider) * @see #addCompletionProvider(CompletionProvider)
*/ */
public RoundRobinAutoCompletion(CompletionProvider provider) { public RoundRobinAutoCompletion(CompletionProvider provider) {
@@ -58,25 +57,24 @@ public class RoundRobinAutoCompletion extends AutoCompletion {
// chosen. // chosen.
setAutoCompleteSingleChoices(false); setAutoCompleteSingleChoices(false);
} }
/** /**
* Adds an additional <code>CompletionProvider</code> to the list to * Adds an additional <code>CompletionProvider</code> to the list to cycle
* cycle through. * through.
* *
* @param provider * @param provider The new completion provider.
* The new completion provider.
*/ */
public void addCompletionProvider(CompletionProvider provider) { public void addCompletionProvider(CompletionProvider provider) {
cycle.add(provider); cycle.add(provider);
} }
/** /**
* Moves to the next Provider internally. Needs refresh of the popup window * Moves to the next Provider internally. Needs refresh of the popup window to
* to display the changes. * display the changes.
* *
* @return true if the next provider was the default one (thus returned to * @return true if the next provider was the default one (thus returned to the
* the default view). May be used in case you like to hide the * default view). May be used in case you like to hide the popup in this
* popup in this case. * case.
*/ */
public boolean advanceProvider() { public boolean advanceProvider() {
CompletionProvider currentProvider = getCompletionProvider(); CompletionProvider currentProvider = getCompletionProvider();
@@ -84,7 +82,7 @@ public class RoundRobinAutoCompletion extends AutoCompletion {
setCompletionProvider(cycle.get(i)); setCompletionProvider(cycle.get(i));
return i == 0; return i == 0;
} }
/** /**
* Overridden to provide our own implementation of the action. * Overridden to provide our own implementation of the action.
*/ */
@@ -92,7 +90,7 @@ public class RoundRobinAutoCompletion extends AutoCompletion {
protected Action createAutoCompleteAction() { protected Action createAutoCompleteAction() {
return new CycleAutoCompleteAction(); return new CycleAutoCompleteAction();
} }
/** /**
* Resets the cycle to use the default provider on next refresh. * Resets the cycle to use the default provider on next refresh.
*/ */
@@ -103,14 +101,14 @@ public class RoundRobinAutoCompletion extends AutoCompletion {
setCompletionProvider(defaultProvider); setCompletionProvider(defaultProvider);
} }
} }
/** /**
* An implementation of the auto-complete action that ensures the proper * An implementation of the auto-complete action that ensures the proper
* <code>CompletionProvider</code> is displayed based on the context in * <code>CompletionProvider</code> is displayed based on the context in which
* which the user presses the trigger key. * the user presses the trigger key.
*/ */
private class CycleAutoCompleteAction extends AutoCompleteAction { private class CycleAutoCompleteAction extends AutoCompleteAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (isAutoCompleteEnabled()) { if (isAutoCompleteEnabled()) {
@@ -17,68 +17,58 @@ package org.fife.ui.autocomplete;
* @version 1.0 * @version 1.0
*/ */
public class ShorthandCompletion extends BasicCompletion { public class ShorthandCompletion extends BasicCompletion {
/** /**
* The text the user can start typing that will match this completion. * The text the user can start typing that will match this completion.
*/ */
private String inputText; private String inputText;
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The provider that returns this completion.
* The provider that returns this completion. * @param inputText The text the user inputs to get this completion.
* @param inputText * @param replacementText The replacement text of the completion.
* The text the user inputs to get this completion.
* @param replacementText
* The replacement text of the completion.
*/ */
public ShorthandCompletion(CompletionProvider provider, String inputText, String replacementText) { public ShorthandCompletion(CompletionProvider provider, String inputText, String replacementText) {
super(provider, replacementText); super(provider, replacementText);
this.inputText = inputText; this.inputText = inputText;
} }
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The provider that returns this completion.
* The provider that returns this completion. * @param inputText The text the user inputs to get this completion.
* @param inputText * @param replacementText The replacement text of the completion.
* The text the user inputs to get this completion. * @param shortDesc A short description of the completion. This will be
* @param replacementText * displayed in the completion list. This may be
* The replacement text of the completion. * <code>null</code>.
* @param shortDesc
* A short description of the completion. This will be
* displayed in the completion list. This may be
* <code>null</code>.
*/ */
public ShorthandCompletion(CompletionProvider provider, String inputText, String replacementText, String shortDesc) { public ShorthandCompletion(CompletionProvider provider, String inputText, String replacementText,
String shortDesc) {
super(provider, replacementText, shortDesc); super(provider, replacementText, shortDesc);
this.inputText = inputText; this.inputText = inputText;
} }
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The provider that returns this completion.
* The provider that returns this completion. * @param inputText The text the user inputs to get this completion.
* @param inputText * @param replacementText The replacement text of the completion.
* The text the user inputs to get this completion. * @param shortDesc A short description of the completion. This will be
* @param replacementText * displayed in the completion list. This may be
* The replacement text of the completion. * <code>null</code>.
* @param shortDesc * @param summary The summary of this completion. This should be HTML.
* A short description of the completion. This will be * This may be <code>null</code>.
* displayed in the completion list. This may be
* <code>null</code>.
* @param summary
* The summary of this completion. This should be HTML.
* This may be <code>null</code>.
*/ */
public ShorthandCompletion(CompletionProvider provider, String inputText, String replacementText, String shortDesc, String summary) { public ShorthandCompletion(CompletionProvider provider, String inputText, String replacementText, String shortDesc,
String summary) {
super(provider, replacementText, shortDesc, summary); super(provider, replacementText, shortDesc, summary);
this.inputText = inputText; this.inputText = inputText;
} }
/** /**
* Returns the text the user must start typing to get this completion. * Returns the text the user must start typing to get this completion.
* *
@@ -88,13 +78,12 @@ public class ShorthandCompletion extends BasicCompletion {
public String getInputText() { public String getInputText() {
return inputText; return inputText;
} }
/** /**
* If a summary has been set, that summary is returned. Otherwise, the * If a summary has been set, that summary is returned. Otherwise, the
* replacement text is returned. * replacement text is returned.
* *
* @return A description of this completion (the text that will be * @return A description of this completion (the text that will be inserted).
* inserted).
* @see #getReplacementText() * @see #getReplacementText()
*/ */
@Override @Override
@@ -102,11 +91,11 @@ public class ShorthandCompletion extends BasicCompletion {
String summary = super.getSummary(); String summary = super.getSummary();
return summary != null ? summary : ("<html><body>" + getSummaryBody()); return summary != null ? summary : ("<html><body>" + getSummaryBody());
} }
/** /**
* Returns the "body" of the HTML returned by {@link #getSummary()} when * Returns the "body" of the HTML returned by {@link #getSummary()} when no
* no summary text has been set. This is defined to return the replacement * summary text has been set. This is defined to return the replacement text in
* text in a monospaced font. * a monospaced font.
* *
* @return The summary text's body, if no other summary has been defined. * @return The summary text's body, if no other summary has been defined.
* @see #getReplacementText() * @see #getReplacementText()
+21 -24
View File
@@ -37,32 +37,31 @@ import javax.swing.event.MouseInputAdapter;
* @version 1.0 * @version 1.0
*/ */
class SizeGrip extends JPanel { class SizeGrip extends JPanel {
/** /**
* The size grip to use if we're on OS X. * The size grip to use if we're on OS X.
*/ */
private Image osxSizeGrip; private Image osxSizeGrip;
public SizeGrip() { public SizeGrip() {
MouseHandler adapter = new MouseHandler(); MouseHandler adapter = new MouseHandler();
addMouseListener(adapter); addMouseListener(adapter);
addMouseMotionListener(adapter); addMouseMotionListener(adapter);
setPreferredSize(new Dimension(16, 16)); setPreferredSize(new Dimension(16, 16));
} }
/** /**
* Overridden to ensure that the cursor for this component is appropriate * Overridden to ensure that the cursor for this component is appropriate for
* for the orientation. * the orientation.
* *
* @param o * @param o The new orientation.
* The new orientation.
*/ */
@Override @Override
public void applyComponentOrientation(ComponentOrientation o) { public void applyComponentOrientation(ComponentOrientation o) {
possiblyFixCursor(o.isLeftToRight()); possiblyFixCursor(o.isLeftToRight());
super.applyComponentOrientation(o); super.applyComponentOrientation(o);
} }
/** /**
* Creates and returns the OS X size grip image. * Creates and returns the OS X size grip image.
* *
@@ -94,12 +93,11 @@ class SizeGrip extends JPanel {
} }
return image; return image;
} }
/** /**
* Paints this panel. * Paints this panel.
* *
* @param g * @param g The graphics context.
* The graphics context.
*/ */
@Override @Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
@@ -147,13 +145,12 @@ class SizeGrip extends JPanel {
g.fillRect(2, height - 9, 2, 2); g.fillRect(2, height - 9, 2, 2);
} }
} }
/** /**
* Ensures that the cursor for this component is appropriate for the * Ensures that the cursor for this component is appropriate for the
* orientation. * orientation.
* *
* @param ltr * @param ltr Whether the current component orientation is LTR.
* Whether the current component orientation is LTR.
*/ */
protected void possiblyFixCursor(boolean ltr) { protected void possiblyFixCursor(boolean ltr) {
int cursor = Cursor.NE_RESIZE_CURSOR; int cursor = Cursor.NE_RESIZE_CURSOR;
@@ -164,7 +161,7 @@ class SizeGrip extends JPanel {
setCursor(Cursor.getPredefinedCursor(cursor)); setCursor(Cursor.getPredefinedCursor(cursor));
} }
} }
@Override @Override
public void updateUI() { public void updateUI() {
super.updateUI(); super.updateUI();
@@ -178,21 +175,21 @@ class SizeGrip extends JPanel {
osxSizeGrip = null; osxSizeGrip = null;
} }
} }
/** /**
* Listens for mouse events on this panel and resizes the parent window * Listens for mouse events on this panel and resizes the parent window
* appropriately. * appropriately.
*/ */
/* /*
* NOTE: We use SwingUtilities.convertPointToScreen() instead of just using * NOTE: We use SwingUtilities.convertPointToScreen() instead of just using the
* the locations relative to the corner component because the latter proved * locations relative to the corner component because the latter proved buggy -
* buggy - stretch the window too wide and some kind of arithmetic error * stretch the window too wide and some kind of arithmetic error started
* started happening somewhere - our window would grow way too large. * happening somewhere - our window would grow way too large.
*/ */
private class MouseHandler extends MouseInputAdapter { private class MouseHandler extends MouseInputAdapter {
private Point origPos; private Point origPos;
@Override @Override
public void mouseDragged(MouseEvent e) { public void mouseDragged(MouseEvent e) {
Point newPos = e.getPoint(); Point newPos = e.getPoint();
@@ -222,13 +219,13 @@ class SizeGrip extends JPanel {
} }
origPos.setLocation(newPos); origPos.setLocation(newPos);
} }
@Override @Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
origPos = e.getPoint(); origPos = e.getPoint();
SwingUtilities.convertPointToScreen(origPos, SizeGrip.this); SwingUtilities.convertPointToScreen(origPos, SizeGrip.this);
} }
@Override @Override
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
origPos = null; origPos = null;
@@ -10,14 +10,14 @@ package org.fife.ui.autocomplete;
import java.util.Comparator; import java.util.Comparator;
/** /**
* Compares two <code>Completion</code>s by their relevance before * Compares two <code>Completion</code>s by their relevance before sorting them
* sorting them lexicographically. * lexicographically.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public class SortByRelevanceComparator implements Comparator<Completion> { public class SortByRelevanceComparator implements Comparator<Completion> {
@Override @Override
public int compare(Completion c1, Completion c2) { public int compare(Completion c1, Completion c2) {
int rel1 = c1.getRelevance(); int rel1 = c1.getRelevance();
@@ -37,12 +37,12 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
* } * }
* </pre> * </pre>
* *
* In the above example, the first <code>${i}</code> is a parameter for the * In the above example, the first <code>${i}</code> is a parameter for the user
* user to type into; all the other <code>${i}</code> instances are * to type into; all the other <code>${i}</code> instances are automatically
* automatically changed to what the user types in the first one. The parameter * changed to what the user types in the first one. The parameter named
* named <code>${cursor}</code> is the "ending position" of the template. It's * <code>${cursor}</code> is the "ending position" of the template. It's where
* where the caret moves after it cycles through all other parameters. If the * the caret moves after it cycles through all other parameters. If the user
* user types into it, template mode terminates. If more than one * types into it, template mode terminates. If more than one
* <code>${cursor}</code> parameter is specified, behavior is undefined. * <code>${cursor}</code> parameter is specified, behavior is undefined.
* <p> * <p>
* *
@@ -51,15 +51,15 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
* fault-tolerant. * fault-tolerant.
* <p> * <p>
* *
* Leading whitespace is automatically added to lines if the template spans * Leading whitespace is automatically added to lines if the template spans more
* more than one line, and if used with a text component using a * than one line, and if used with a text component using a
* <code>PlainDocument</code>, tabs will be converted to spaces if requested. * <code>PlainDocument</code>, tabs will be converted to spaces if requested.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public class TemplateCompletion extends AbstractCompletion implements ParameterizedCompletion { public class TemplateCompletion extends AbstractCompletion implements ParameterizedCompletion {
private List<TemplatePiece> pieces; private List<TemplatePiece> pieces;
private String inputText; private String inputText;
private String definitionString; private String definitionString;
@@ -69,11 +69,11 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
* The template's parameters. * The template's parameters.
*/ */
private List<Parameter> params; private List<Parameter> params;
public TemplateCompletion(CompletionProvider provider, String inputText, String definitionString, String template) { public TemplateCompletion(CompletionProvider provider, String inputText, String definitionString, String template) {
this(provider, inputText, definitionString, template, null, null); this(provider, inputText, definitionString, template, null, null);
} }
public TemplateCompletion(CompletionProvider provider, String inputText, String definitionString, String template, public TemplateCompletion(CompletionProvider provider, String inputText, String definitionString, String template,
String shortDescription, String summary) { String shortDescription, String summary) {
super(provider); super(provider);
@@ -85,7 +85,7 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
params = new ArrayList<Parameter>(3); params = new ArrayList<Parameter>(3);
parse(template); parse(template);
} }
private void addTemplatePiece(TemplatePiece piece) { private void addTemplatePiece(TemplatePiece piece) {
pieces.add(piece); pieces.add(piece);
if (piece instanceof Param && !"cursor".equals(piece.getText())) { if (piece instanceof Param && !"cursor".equals(piece.getText())) {
@@ -94,12 +94,12 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
params.add(param); params.add(param);
} }
} }
@Override @Override
public String getInputText() { public String getInputText() {
return inputText; return inputText;
} }
private String getPieceText(int index, String leadingWS) { private String getPieceText(int index, String leadingWS) {
TemplatePiece piece = pieces.get(index); TemplatePiece piece = pieces.get(index);
String text = piece.getText(); String text = piece.getText();
@@ -108,10 +108,10 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
} }
return text; return text;
} }
/** /**
* Returns <code>null</code>; template completions insert all of their * Returns <code>null</code>; template completions insert all of their text via
* text via <code>getInsertionInfo()</code>. * <code>getInsertionInfo()</code>.
* *
* @return <code>null</code> always. * @return <code>null</code> always.
*/ */
@@ -119,21 +119,21 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
public String getReplacementText() { public String getReplacementText() {
return null; return null;
} }
@Override @Override
public String getSummary() { public String getSummary() {
return summary; return summary;
} }
@Override @Override
public String getDefinitionString() { public String getDefinitionString() {
return definitionString; return definitionString;
} }
public String getShortDescription() { public String getShortDescription() {
return shortDescription; return shortDescription;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -141,7 +141,7 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
public boolean getShowParameterToolTip() { public boolean getShowParameterToolTip() {
return false; return false;
} }
@Override @Override
public ParameterizedCompletionInsertionInfo getInsertionInfo(JTextComponent tc, boolean replaceTabsWithSpaces) { public ParameterizedCompletionInsertionInfo getInsertionInfo(JTextComponent tc, boolean replaceTabsWithSpaces) {
ParameterizedCompletionInsertionInfo info = new ParameterizedCompletionInsertionInfo(); ParameterizedCompletionInsertionInfo info = new ParameterizedCompletionInsertionInfo();
@@ -214,7 +214,7 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
info.setTextToInsert(sb.toString()); info.setTextToInsert(sb.toString());
return info; return info;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -222,7 +222,7 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
public Parameter getParam(int index) { public Parameter getParam(int index) {
return params.get(index); return params.get(index);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -230,12 +230,11 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
public int getParamCount() { public int getParamCount() {
return params == null ? 0 : params.size(); return params == null ? 0 : params.size();
} }
/** /**
* Returns whether a parameter is already defined with a specific name. * Returns whether a parameter is already defined with a specific name.
* *
* @param name * @param name The name.
* The name.
* @return Whether a parameter is defined with that name. * @return Whether a parameter is defined with that name.
*/ */
private boolean isParamDefined(String name) { private boolean isParamDefined(String name) {
@@ -247,12 +246,11 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
} }
return false; return false;
} }
/** /**
* Parses a template string into logical pieces used by this class. * Parses a template string into logical pieces used by this class.
* *
* @param template * @param template The template to parse.
* The template to parse.
*/ */
private void parse(String template) { private void parse(String template) {
int offs = 0; int offs = 0;
@@ -260,23 +258,23 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
while ((offs = template.indexOf('$', lastOffs)) > -1 && offs < template.length() - 1) { while ((offs = template.indexOf('$', lastOffs)) > -1 && offs < template.length() - 1) {
char next = template.charAt(offs + 1); char next = template.charAt(offs + 1);
switch (next) { switch (next) {
case '$': // "$$" => escaped single dollar sign case '$': // "$$" => escaped single dollar sign
addTemplatePiece(new TemplatePiece.Text(template.substring(lastOffs, offs + 1))); addTemplatePiece(new TemplatePiece.Text(template.substring(lastOffs, offs + 1)));
lastOffs = offs + 2; lastOffs = offs + 2;
break; break;
case '{': // "${...}" => variable case '{': // "${...}" => variable
int closingCurly = template.indexOf('}', offs + 2); int closingCurly = template.indexOf('}', offs + 2);
if (closingCurly > -1) { if (closingCurly > -1) {
addTemplatePiece(new TemplatePiece.Text(template.substring(lastOffs, offs))); addTemplatePiece(new TemplatePiece.Text(template.substring(lastOffs, offs)));
String varName = template.substring(offs + 2, closingCurly); String varName = template.substring(offs + 2, closingCurly);
if (!"cursor".equals(varName) && isParamDefined(varName)) { if (!"cursor".equals(varName) && isParamDefined(varName)) {
addTemplatePiece(new TemplatePiece.ParamCopy(varName)); addTemplatePiece(new TemplatePiece.ParamCopy(varName));
} else { } else {
addTemplatePiece(new TemplatePiece.Param(varName)); addTemplatePiece(new TemplatePiece.Param(varName));
}
lastOffs = closingCurly + 1;
} }
break; lastOffs = closingCurly + 1;
}
break;
} }
} }
if (lastOffs < template.length()) { if (lastOffs < template.length()) {
@@ -284,7 +282,7 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
addTemplatePiece(new TemplatePiece.Text(text)); addTemplatePiece(new TemplatePiece.Text(text));
} }
} }
private int possiblyReplaceTabsWithSpaces(StringBuilder sb, String text, JTextComponent tc, int start) { private int possiblyReplaceTabsWithSpaces(StringBuilder sb, String text, JTextComponent tc, int start) {
int tab = text.indexOf('\t'); int tab = text.indexOf('\t');
if (tab > -1) { if (tab > -1) {
@@ -315,18 +313,17 @@ public class TemplateCompletion extends AbstractCompletion implements Parameteri
} }
return start; return start;
} }
/** /**
* Sets the short description of this template completion. * Sets the short description of this template completion.
* *
* @param shortDesc * @param shortDesc The new short description.
* The new short description.
* @see #getShortDescription() * @see #getShortDescription()
*/ */
public void setShortDescription(String shortDesc) { public void setShortDescription(String shortDesc) {
this.shortDescription = shortDesc; this.shortDescription = shortDesc;
} }
@Override @Override
public String toString() { public String toString() {
return getDefinitionString(); return getDefinitionString();
+18 -18
View File
@@ -7,68 +7,68 @@
package org.fife.ui.autocomplete; package org.fife.ui.autocomplete;
/** /**
* A piece of a <code>TemplateCompletion</code>. You add instances of this * A piece of a <code>TemplateCompletion</code>. You add instances of this class
* class to template completions to define them. * to template completions to define them.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
* @see TemplateCompletion * @see TemplateCompletion
*/ */
interface TemplatePiece { interface TemplatePiece {
String getText(); String getText();
public class Text implements TemplatePiece { public class Text implements TemplatePiece {
private String text; private String text;
public Text(String text) { public Text(String text) {
this.text = text; this.text = text;
} }
@Override @Override
public String getText() { public String getText() {
return text; return text;
} }
@Override @Override
public String toString() { public String toString() {
return "[TemplatePiece.Text: text=" + text + "]"; return "[TemplatePiece.Text: text=" + text + "]";
} }
} }
public class Param implements TemplatePiece { public class Param implements TemplatePiece {
String text; String text;
public Param(String text) { public Param(String text) {
this.text = text; this.text = text;
} }
@Override @Override
public String getText() { public String getText() {
return text; return text;
} }
@Override @Override
public String toString() { public String toString() {
return "[TemplatePiece.Param: param=" + text + "]"; return "[TemplatePiece.Param: param=" + text + "]";
} }
} }
public class ParamCopy implements TemplatePiece { public class ParamCopy implements TemplatePiece {
private String text; private String text;
public ParamCopy(String text) { public ParamCopy(String text) {
this.text = text; this.text = text;
} }
@Override @Override
public String getText() { public String getText() {
return text; return text;
} }
@Override @Override
public String toString() { public String toString() {
return "[TemplatePiece.ParamCopy: param=" + text + "]"; return "[TemplatePiece.ParamCopy: param=" + text + "]";
+23 -24
View File
@@ -22,17 +22,18 @@ import javax.swing.text.html.HTMLDocument;
* Static utility methods for homemade tool tips. * Static utility methods for homemade tool tips.
* <p> * <p>
* *
* This is blatantly ripped off from RSyntaxTextArea's "FocusableTips" class * This is blatantly ripped off from RSyntaxTextArea's "FocusableTips" class of
* of the same name, but isn't re-used to prevent a hard dependency on the * the same name, but isn't re-used to prevent a hard dependency on the RSTA
* RSTA library. * library.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
class TipUtil { class TipUtil {
private TipUtil() {} private TipUtil() {
}
/** /**
* Returns the default background color to use for tool tip windows. * Returns the default background color to use for tool tip windows.
* *
@@ -55,7 +56,7 @@ class TipUtil {
} }
return c; return c;
} }
/** /**
* Returns the border used by tool tips in this look and feel. * Returns the border used by tool tips in this look and feel.
* *
@@ -71,21 +72,20 @@ class TipUtil {
} }
return border; return border;
} }
/** /**
* Returns whether a color is a Nimbus DerivedColor, which is troublesome * Returns whether a color is a Nimbus DerivedColor, which is troublesome in
* in that it doesn't use its RGB values (uses HSB instead?) and so * that it doesn't use its RGB values (uses HSB instead?) and so querying them
* querying them is useless. * is useless.
* *
* @param c * @param c The color to check.
* The color to check.
* @return Whether it is a DerivedColor * @return Whether it is a DerivedColor
*/ */
private static final boolean isDerivedColor(Color c) { private static final boolean isDerivedColor(Color c) {
return c != null return c != null && (c.getClass().getName().endsWith(".DerivedColor")
&& (c.getClass().getName().endsWith(".DerivedColor") || c.getClass().getName().endsWith(".DerivedColor$UIResource")); || c.getClass().getName().endsWith(".DerivedColor$UIResource"));
} }
/** /**
* Returns whether the Nimbus Look and Feel is installed. * Returns whether the Nimbus Look and Feel is installed.
* *
@@ -94,14 +94,13 @@ class TipUtil {
private static final boolean isNimbusLookAndFeel() { private static final boolean isNimbusLookAndFeel() {
return UIManager.getLookAndFeel().getName().equals("Nimbus"); return UIManager.getLookAndFeel().getName().equals("Nimbus");
} }
/** /**
* Tweaks a <code>JEditorPane</code> so it can be used to render the * Tweaks a <code>JEditorPane</code> so it can be used to render the content in
* content in a focusable pseudo-tool tip. It is assumed that the editor * a focusable pseudo-tool tip. It is assumed that the editor pane is using an
* pane is using an <code>HTMLDocument</code>. * <code>HTMLDocument</code>.
* *
* @param textArea * @param textArea The editor pane to tweak.
* The editor pane to tweak.
*/ */
public static void tweakTipEditorPane(JEditorPane textArea) { public static void tweakTipEditorPane(JEditorPane textArea) {
// Jump through a few hoops to get things looking nice in Nimbus // Jump through a few hoops to get things looking nice in Nimbus
@@ -134,8 +133,8 @@ class TipUtil {
font = new Font("SansSerif", Font.PLAIN, 12); font = new Font("SansSerif", Font.PLAIN, 12);
} }
HTMLDocument doc = (HTMLDocument) textArea.getDocument(); HTMLDocument doc = (HTMLDocument) textArea.getDocument();
doc.getStyleSheet().addRule("body { font-family: " + font.getFamily() + "; font-size: " + font.getSize() + "pt" + "; color: " doc.getStyleSheet().addRule("body { font-family: " + font.getFamily() + "; font-size: " + font.getSize() + "pt"
+ Util.getHexString(fg) + "; }"); + "; color: " + Util.getHexString(fg) + "; }");
// Always add link foreground rule. Unfortunately these CSS rules // Always add link foreground rule. Unfortunately these CSS rules
// stack each time the LaF is changed (how can we overwrite them // stack each time the LaF is changed (how can we overwrite them
// without clearing out the important "standard" ones?). // without clearing out the important "standard" ones?).
+59 -67
View File
@@ -28,31 +28,31 @@ import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator;
* @version 1.0 * @version 1.0
*/ */
public class Util { public class Util {
/** /**
* If a system property is defined with this name and set, ignoring case, * If a system property is defined with this name and set, ignoring case, to
* to <code>true</code>, this library will not attempt to use Substance * <code>true</code>, this library will not attempt to use Substance renderers.
* renderers. Otherwise, if a Substance Look and Feel is installed, we * Otherwise, if a Substance Look and Feel is installed, we will attempt to use
* will attempt to use Substance cell renderers in all of our dropdowns. * Substance cell renderers in all of our dropdowns.
* <p> * <p>
* *
* Note that we do not have a build dependency on Substance, so all access * Note that we do not have a build dependency on Substance, so all access to
* to Substance stuff is done via reflection. We will fall back onto * Substance stuff is done via reflection. We will fall back onto default
* default renderers if something goes horribly wrong. * renderers if something goes horribly wrong.
*/ */
public static final String PROPERTY_DONT_USE_SUBSTANCE_RENDERERS = "org.fife.ui.autocomplete.DontUseSubstanceRenderers"; public static final String PROPERTY_DONT_USE_SUBSTANCE_RENDERERS = "org.fife.ui.autocomplete.DontUseSubstanceRenderers";
/** /**
* If this system property is <code>true</code>, then even the "main" two * If this system property is <code>true</code>, then even the "main" two
* auto-complete windows will allow window decorations via * auto-complete windows will allow window decorations via
* {@link PopupWindowDecorator}. If this property is undefined or * {@link PopupWindowDecorator}. If this property is undefined or
* <code>false</code>, they won't honor such decorations. This is due to * <code>false</code>, they won't honor such decorations. This is due to certain
* certain performance issues with translucent windows (used for drop * performance issues with translucent windows (used for drop shadows), even as
* shadows), even as of Java 7u2. * of Java 7u2.
*/ */
public static final String PROPERTY_ALLOW_DECORATED_AUTOCOMPLETE_WINDOWS = "org.fife.ui.autocomplete.allowDecoratedAutoCompleteWindows"; public static final String PROPERTY_ALLOW_DECORATED_AUTOCOMPLETE_WINDOWS = "org.fife.ui.autocomplete.allowDecoratedAutoCompleteWindows";
/** /**
* Used for the color of hyperlinks when a LookAndFeel uses light text * Used for the color of hyperlinks when a LookAndFeel uses light text against a
* against a dark background. * dark background.
*/ */
private static final Color LIGHT_HYPERLINK_FG = new Color(0xd8ffff); private static final Color LIGHT_HYPERLINK_FG = new Color(0xd8ffff);
private static final Pattern TAG_PATTERN = Pattern.compile("<[^>]*>"); private static final Pattern TAG_PATTERN = Pattern.compile("<[^>]*>");
@@ -60,15 +60,14 @@ public class Util {
private static boolean desktopCreationAttempted; private static boolean desktopCreationAttempted;
private static Object desktop; private static Object desktop;
private static final Object LOCK_DESKTOP_CREATION = new Object(); private static final Object LOCK_DESKTOP_CREATION = new Object();
/** /**
* Attempts to open a web browser to the specified URI. * Attempts to open a web browser to the specified URI.
* *
* @param uri * @param uri The URI to open. If this is <code>null</code>, nothing happens and
* The URI to open. If this is <code>null</code>, nothing * this method returns <code>false</code>.
* happens and this method returns <code>false</code>. * @return Whether the operation was successful. This will be <code>false</code>
* @return Whether the operation was successful. This will be * on JRE's older than 1.6.
* <code>false</code> on JRE's older than 1.6.
*/ */
public static boolean browse(URI uri) { public static boolean browse(URI uri) {
boolean success = false; boolean success = false;
@@ -88,11 +87,11 @@ public class Util {
} }
return success; return success;
} }
/** /**
* Returns the singleton <code>java.awt.Desktop</code> instance, or * Returns the singleton <code>java.awt.Desktop</code> instance, or
* <code>null</code> if it is unsupported on this platform (or the JRE * <code>null</code> if it is unsupported on this platform (or the JRE is older
* is older than 1.6). * than 1.6).
* *
* @return The desktop, as an {@link Object}. * @return The desktop, as an {@link Object}.
*/ */
@@ -117,14 +116,13 @@ public class Util {
} }
return desktop; return desktop;
} }
/** /**
* Returns a hex string for the specified color, suitable for HTML. * Returns a hex string for the specified color, suitable for HTML.
* *
* @param c * @param c The color.
* The color. * @return The string representation, in the form "<code>#rrggbb</code>", or
* @return The string representation, in the form "<code>#rrggbb</code>", * <code>null</code> if <code>c</code> is <code>null</code>.
* or <code>null</code> if <code>c</code> is <code>null</code>.
*/ */
public static String getHexString(Color c) { public static String getHexString(Color c) {
if (c == null) { if (c == null) {
@@ -150,12 +148,12 @@ public class Util {
sb.append(Integer.toHexString(b)); sb.append(Integer.toHexString(b));
return sb.toString(); return sb.toString();
} }
/** /**
* Returns the color to use for hyperlink-style components. This method * Returns the color to use for hyperlink-style components. This method will
* will return <code>Color.blue</code> unless it appears that the current * return <code>Color.blue</code> unless it appears that the current LookAndFeel
* LookAndFeel uses light text on a dark background, in which case a * uses light text on a dark background, in which case a brighter alternative is
* brighter alternative is returned. * returned.
* *
* @return The color to use for hyperlinks. * @return The color to use for hyperlinks.
*/ */
@@ -168,16 +166,14 @@ public class Util {
} }
return isLightForeground(fg) ? LIGHT_HYPERLINK_FG : Color.blue; return isLightForeground(fg) ? LIGHT_HYPERLINK_FG : Color.blue;
} }
/** /**
* Returns the screen coordinates for the monitor that contains the * Returns the screen coordinates for the monitor that contains the specified
* specified point. This is useful for setups with multiple monitors, * point. This is useful for setups with multiple monitors, to ensure that popup
* to ensure that popup windows are positioned properly. * windows are positioned properly.
* *
* @param x * @param x The x-coordinate, in screen coordinates.
* The x-coordinate, in screen coordinates. * @param y The y-coordinate, in screen coordinates.
* @param y
* The y-coordinate, in screen coordinates.
* @return The bounds of the monitor that contains the specified point. * @return The bounds of the monitor that contains the specified point.
*/ */
public static Rectangle getScreenBoundsForPoint(int x, int y) { public static Rectangle getScreenBoundsForPoint(int x, int y) {
@@ -193,12 +189,12 @@ public class Util {
// If point is outside all monitors, default to default monitor (?) // If point is outside all monitors, default to default monitor (?)
return env.getMaximumWindowBounds(); return env.getMaximumWindowBounds();
} }
/** /**
* Give apps a chance to decorate us with drop shadows, etc. Since very * Give apps a chance to decorate us with drop shadows, etc. Since very scrolly
* scrolly things such as lists (of e.g. completions) are *very* slow when * things such as lists (of e.g. completions) are *very* slow when in per-pixel
* in per-pixel translucent windows, even as of Java 7u2, we force the user * translucent windows, even as of Java 7u2, we force the user to specify an
* to specify an extra option for the two "main" auto-complete windows. * extra option for the two "main" auto-complete windows.
* *
* @return Whether to allow decorating the main auto-complete windows. * @return Whether to allow decorating the main auto-complete windows.
* @see #PROPERTY_ALLOW_DECORATED_AUTOCOMPLETE_WINDOWS * @see #PROPERTY_ALLOW_DECORATED_AUTOCOMPLETE_WINDOWS
@@ -210,40 +206,37 @@ public class Util {
return false; return false;
} }
} }
/** /**
* Returns whether we should attempt to use Substance cell renderers and * Returns whether we should attempt to use Substance cell renderers and styles
* styles for things such as completion choices, if a Substance Look and * for things such as completion choices, if a Substance Look and Feel is
* Feel is installed. If this is <code>false</code>, we'll use our * installed. If this is <code>false</code>, we'll use our standard rendering
* standard rendering for completions, even when Substance is being used. * for completions, even when Substance is being used.
* *
* @return Whether to use Substance renderers if Substance is installed. * @return Whether to use Substance renderers if Substance is installed.
*/ */
public static boolean getUseSubstanceRenderers() { public static boolean getUseSubstanceRenderers() {
return useSubstanceRenderers; return useSubstanceRenderers;
} }
/** /**
* Returns whether the specified color is "light" to use as a foreground. * Returns whether the specified color is "light" to use as a foreground. Colors
* Colors that return <code>true</code> indicate that the current Look and * that return <code>true</code> indicate that the current Look and Feel
* Feel probably uses light text colors on a dark background. * probably uses light text colors on a dark background.
* *
* @param fg * @param fg The foreground color.
* The foreground color.
* @return Whether it is a "light" foreground color. * @return Whether it is a "light" foreground color.
*/ */
public static final boolean isLightForeground(Color fg) { public static final boolean isLightForeground(Color fg) {
return fg.getRed() > 0xa0 && fg.getGreen() > 0xa0 && fg.getBlue() > 0xa0; return fg.getRed() > 0xa0 && fg.getGreen() > 0xa0 && fg.getBlue() > 0xa0;
} }
/** /**
* Returns whether a string starts with a specified prefix, ignoring case. * Returns whether a string starts with a specified prefix, ignoring case. This
* This method does not support characters outside of the BMP. * method does not support characters outside of the BMP.
* *
* @param str * @param str The string to check. This cannot be {@code null}.
* The string to check. This cannot be {@code null}. * @param prefix The prefix to check for. This cannot be {@code null}.
* @param prefix
* The prefix to check for. This cannot be {@code null}.
* @return Whether {@code str} starts with {@code prefix}, ignoring case. * @return Whether {@code str} starts with {@code prefix}, ignoring case.
*/ */
public static boolean startsWithIgnoreCase(String str, String prefix) { public static boolean startsWithIgnoreCase(String str, String prefix) {
@@ -253,13 +246,12 @@ public class Util {
} }
return false; return false;
} }
/** /**
* Strips any HTML from a string. The string must start with * Strips any HTML from a string. The string must start with
* "<code>&lt;html&gt;</code>" for markup tags to be stripped. * "<code>&lt;html&gt;</code>" for markup tags to be stripped.
* *
* @param text * @param text The string.
* The string.
* @return The string, with any HTML stripped. * @return The string, with any HTML stripped.
*/ */
public static String stripHtml(String text) { public static String stripHtml(String text) {
@@ -269,7 +261,7 @@ public class Util {
// TODO: Micro-optimize me, might be called in renderers and loops // TODO: Micro-optimize me, might be called in renderers and loops
return TAG_PATTERN.matcher(text).replaceAll(""); return TAG_PATTERN.matcher(text).replaceAll("");
} }
static { static {
boolean use = true; boolean use = true;
try { try {
@@ -13,16 +13,16 @@ import javax.swing.text.JTextComponent;
* <p> * <p>
* *
* This completion type uses its <tt>shortDescription</tt> property as part of * This completion type uses its <tt>shortDescription</tt> property as part of
* its summary returned by {@link #getSummary()}; for this reason, it may be * its summary returned by {@link #getSummary()}; for this reason, it may be a
* a little longer (even much longer), if desired, than what is recommended * little longer (even much longer), if desired, than what is recommended for
* for <tt>BasicCompletion</tt>s (where the <tt>shortDescription</tt> is used * <tt>BasicCompletion</tt>s (where the <tt>shortDescription</tt> is used in
* in {@link #toString()} for <tt>ListCellRenderers</tt>). * {@link #toString()} for <tt>ListCellRenderers</tt>).
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public class VariableCompletion extends BasicCompletion { public class VariableCompletion extends BasicCompletion {
/** /**
* The variable's type. * The variable's type.
*/ */
@@ -31,27 +31,24 @@ public class VariableCompletion extends BasicCompletion {
* What library (for example) this variable is defined in. * What library (for example) this variable is defined in.
*/ */
private String definedIn; private String definedIn;
/** /**
* Constructor. * Constructor.
* *
* @param provider * @param provider The parent provider.
* The parent provider. * @param name The name of this variable.
* @param name * @param type The type of this variable (e.g. "<code>int</code>",
* The name of this variable. * "<code>String</code>", etc.).
* @param type
* The type of this variable (e.g. "<code>int</code>",
* "<code>String</code>", etc.).
*/ */
public VariableCompletion(CompletionProvider provider, String name, String type) { public VariableCompletion(CompletionProvider provider, String name, String type) {
super(provider, name); super(provider, name);
this.type = type; this.type = type;
} }
protected void addDefinitionString(StringBuilder sb) { protected void addDefinitionString(StringBuilder sb) {
sb.append("<html><b>").append(getDefinitionString()).append("</b>"); sb.append("<html><b>").append(getDefinitionString()).append("</b>");
} }
public String getDefinitionString() { public String getDefinitionString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
// Add the return type if applicable (C macros like NULL have no type). // Add the return type if applicable (C macros like NULL have no type).
@@ -62,7 +59,7 @@ public class VariableCompletion extends BasicCompletion {
sb.append(getName()); sb.append(getName());
return sb.toString(); return sb.toString();
} }
/** /**
* Returns where this variable is defined. * Returns where this variable is defined.
* *
@@ -72,7 +69,7 @@ public class VariableCompletion extends BasicCompletion {
public String getDefinedIn() { public String getDefinedIn() {
return definedIn; return definedIn;
} }
/** /**
* Returns the name of this variable. * Returns the name of this variable.
* *
@@ -81,7 +78,7 @@ public class VariableCompletion extends BasicCompletion {
public String getName() { public String getName() {
return getReplacementText(); return getReplacementText();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -93,29 +90,25 @@ public class VariableCompletion extends BasicCompletion {
possiblyAddDefinedIn(sb); possiblyAddDefinedIn(sb);
return sb.toString(); return sb.toString();
} }
/** /**
* Returns the tool tip text to display for mouse hovers over this * Returns the tool tip text to display for mouse hovers over this completion.
* completion.
* <p> * <p>
* *
* Note that for this functionality to be enabled, a * Note that for this functionality to be enabled, a <tt>JTextComponent</tt>
* <tt>JTextComponent</tt> must be registered with the * must be registered with the <tt>ToolTipManager</tt>, and the text component
* <tt>ToolTipManager</tt>, and the text component must know to search * must know to search for this value. In the case of an
* for this value. In the case of an * <a href="http://fifesoft.com/rsyntaxtextarea">RSyntaxTextArea</a>, this can
* <a href="http://fifesoft.com/rsyntaxtextarea">RSyntaxTextArea</a>, this * be done with a <tt>org.fife.ui.rtextarea.ToolTipSupplier</tt> that calls into
* can be done with a <tt>org.fife.ui.rtextarea.ToolTipSupplier</tt> that
* calls into
* {@link CompletionProvider#getCompletionsAt(JTextComponent, java.awt.Point)}. * {@link CompletionProvider#getCompletionsAt(JTextComponent, java.awt.Point)}.
* *
* @return The tool tip text for this completion, or <code>null</code> if * @return The tool tip text for this completion, or <code>null</code> if none.
* none.
*/ */
@Override @Override
public String getToolTipText() { public String getToolTipText() {
return getDefinitionString(); return getDefinitionString();
} }
/** /**
* Returns the type of this variable. * Returns the type of this variable.
* *
@@ -124,13 +117,12 @@ public class VariableCompletion extends BasicCompletion {
public String getType() { public String getType() {
return type; return type;
} }
/** /**
* Adds some HTML describing where this variable is defined, if this * Adds some HTML describing where this variable is defined, if this information
* information is known. * is known.
* *
* @param sb * @param sb The buffer to append to.
* The buffer to append to.
*/ */
protected void possiblyAddDefinedIn(StringBuilder sb) { protected void possiblyAddDefinedIn(StringBuilder sb) {
if (definedIn != null) { if (definedIn != null) {
@@ -138,13 +130,11 @@ public class VariableCompletion extends BasicCompletion {
sb.append(" <em>").append(definedIn).append("</em>"); sb.append(" <em>").append(definedIn).append("</em>");
} }
} }
/** /**
* Adds the description text as HTML to a buffer, if a description is * Adds the description text as HTML to a buffer, if a description is defined.
* defined.
* *
* @param sb * @param sb The buffer to append to.
* The buffer to append to.
* @return Whether there was a description to add. * @return Whether there was a description to add.
*/ */
protected boolean possiblyAddDescription(StringBuilder sb) { protected boolean possiblyAddDescription(StringBuilder sb) {
@@ -156,18 +146,17 @@ public class VariableCompletion extends BasicCompletion {
} }
return false; return false;
} }
/** /**
* Sets where this variable is defined. * Sets where this variable is defined.
* *
* @param definedIn * @param definedIn Where this variable is defined.
* Where this variable is defined.
* @see #getDefinedIn() * @see #getDefinedIn()
*/ */
public void setDefinedIn(String definedIn) { public void setDefinedIn(String definedIn) {
this.definedIn = definedIn; this.definedIn = definedIn;
} }
/** /**
* Overridden to return the name of the variable being completed. * Overridden to return the name of the variable being completed.
* *
@@ -30,18 +30,18 @@ import org.fife.ui.rtextarea.RTextArea;
* @version 1.0 * @version 1.0
*/ */
public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker { public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker {
private final Action INSERT_BREAK_ACTION; private final Action INSERT_BREAK_ACTION;
private static final Pattern MLC_PATTERN = Pattern.compile("([ \\t]*)(/?[\\*]+)([ \\t]*)"); private static final Pattern MLC_PATTERN = Pattern.compile("([ \\t]*)(/?[\\*]+)([ \\t]*)");
protected AbstractJFlexCTokenMaker() { protected AbstractJFlexCTokenMaker() {
INSERT_BREAK_ACTION = createInsertBreakAction(); INSERT_BREAK_ACTION = createInsertBreakAction();
} }
/** /**
* Creates and returns the action to use when the user inserts a newline. * Creates and returns the action to use when the user inserts a newline. The
* The default implementation intelligently closes multi-line comments. * default implementation intelligently closes multi-line comments. Subclasses
* Subclasses can override. * can override.
* *
* @return The action. * @return The action.
* @see #getInsertBreakAction() * @see #getInsertBreakAction()
@@ -49,10 +49,10 @@ public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker {
protected Action createInsertBreakAction() { protected Action createInsertBreakAction() {
return new CStyleInsertBreakAction(); return new CStyleInsertBreakAction();
} }
/** /**
* Returns <code>true</code> always as C-style languages use curly braces * Returns <code>true</code> always as C-style languages use curly braces to
* to denote code blocks. * denote code blocks.
* *
* @return <code>true</code> always. * @return <code>true</code> always.
*/ */
@@ -60,11 +60,10 @@ public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker {
public boolean getCurlyBracesDenoteCodeBlocks(int languageIndex) { public boolean getCurlyBracesDenoteCodeBlocks(int languageIndex) {
return true; return true;
} }
/** /**
* Returns an action to handle "insert break" key presses (i.e. Enter). * Returns an action to handle "insert break" key presses (i.e. Enter). An
* An action is returned that handles newlines differently in multi-line * action is returned that handles newlines differently in multi-line comments.
* comments.
* *
* @return The action. * @return The action.
*/ */
@@ -72,7 +71,7 @@ public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker {
public Action getInsertBreakAction() { public Action getInsertBreakAction() {
return INSERT_BREAK_ACTION; return INSERT_BREAK_ACTION;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -80,7 +79,7 @@ public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker {
public boolean getMarkOccurrencesOfTokenType(int type) { public boolean getMarkOccurrencesOfTokenType(int type) {
return type == Token.IDENTIFIER || type == Token.FUNCTION; return type == Token.IDENTIFIER || type == Token.FUNCTION;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -92,19 +91,17 @@ public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker {
} }
return false; return false;
} }
/** /**
* Returns whether a given token is an internal token type that represents * Returns whether a given token is an internal token type that represents an
* an MLC or documentation comment continuing on to the next line. This is * MLC or documentation comment continuing on to the next line. This is done by
* done by languages such as JavaScript that are a little more verbose * languages such as JavaScript that are a little more verbose than necessary so
* than necessary so that their code can be copy-and-pasted into other * that their code can be copy-and-pasted into other <code>TokenMaker</code>s
* <code>TokenMaker</code>s that use them as nested languages (such as * that use them as nested languages (such as HTML, JSP, etc.).
* HTML, JSP, etc.).
* *
* @param t * @param t The token to check. This cannot be <code>null</code>.
* The token to check. This cannot be <code>null</code>. * @return Whether the token is an internal token representing the end of a line
* @return Whether the token is an internal token representing the end of * for an MLC/doc comment continuing on to the next line.
* a line for an MLC/doc comment continuing on to the next line.
*/ */
private boolean isInternalEolTokenForMLCs(Token t) { private boolean isInternalEolTokenForMLCs(Token t) {
int type = t.getType(); int type = t.getType();
@@ -114,13 +111,13 @@ public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker {
} }
return false; return false;
} }
/** /**
* Action that knows how to special-case inserting a newline in a * Action that knows how to special-case inserting a newline in a multi-line
* multi-line comment for languages like C and Java. * comment for languages like C and Java.
*/ */
protected class CStyleInsertBreakAction extends RSyntaxTextAreaEditorKit.InsertBreakAction { protected class CStyleInsertBreakAction extends RSyntaxTextAreaEditorKit.InsertBreakAction {
@Override @Override
public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {
if (!textArea.isEditable() || !textArea.isEnabled()) { if (!textArea.isEditable() || !textArea.isEnabled()) {
@@ -141,13 +138,12 @@ public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker {
handleInsertBreak(rsta, true); handleInsertBreak(rsta, true);
} }
} }
/** /**
* Returns whether the MLC token containing <code>offs</code> appears * Returns whether the MLC token containing <code>offs</code> appears to have a
* to have a "nested" comment (i.e., contains "<code>/*</code>" * "nested" comment (i.e., contains "<code>/*</code>" somewhere inside of it).
* somewhere inside of it). This implies that it is likely a "new" MLC * This implies that it is likely a "new" MLC and needs to be closed. While not
* and needs to be closed. While not foolproof, this is usually good * foolproof, this is usually good enough of a sign.
* enough of a sign.
* *
* @param textArea * @param textArea
* @param line * @param line
@@ -183,7 +179,7 @@ public abstract class AbstractJFlexCTokenMaker extends AbstractJFlexTokenMaker {
} }
return true; // No match - MLC goes to the end of the file return true; // No match - MLC goes to the end of the file
} }
private void insertBreakInMLC(ActionEvent e, RSyntaxTextArea textArea, int line) { private void insertBreakInMLC(ActionEvent e, RSyntaxTextArea textArea, int line) {
Matcher m = null; Matcher m = null;
int start = -1; int start = -1;
@@ -11,35 +11,32 @@ import javax.swing.text.Segment;
/** /**
* Base class for JFlex-generated token makers. This class attempts to factor * Base class for JFlex-generated token makers. This class attempts to factor
* out all common code from these classes. Many methods <em>almost</em> could * out all common code from these classes. Many methods <em>almost</em> could be
* be factored out into this class, but cannot because they reference JFlex * factored out into this class, but cannot because they reference JFlex
* variables that we cannot access from this class. * variables that we cannot access from this class.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 0.1 * @version 0.1
*/ */
public abstract class AbstractJFlexTokenMaker extends TokenMakerBase { public abstract class AbstractJFlexTokenMaker extends TokenMakerBase {
protected Segment s; protected Segment s;
protected int start; // Just for states. protected int start; // Just for states.
protected int offsetShift; // As parser always starts at 0, but our line protected int offsetShift; // As parser always starts at 0, but our line
// doesn't. // doesn't.
/** /**
* Declared here so we can define overloads that refer to this method. * Declared here so we can define overloads that refer to this method.
* *
* @param newState * @param newState The new JFlex state to enter.
* The new JFlex state to enter.
*/ */
public abstract void yybegin(int newState); public abstract void yybegin(int newState);
/** /**
* Starts a new JFlex state and changes the current language index. * Starts a new JFlex state and changes the current language index.
* *
* @param state * @param state The new JFlex state to enter.
* The new JFlex state to enter. * @param languageIndex The new language index.
* @param languageIndex
* The new language index.
*/ */
protected void yybegin(int state, int languageIndex) { protected void yybegin(int state, int languageIndex) {
yybegin(state); yybegin(state);
@@ -8,9 +8,9 @@ package org.fife.ui.rsyntaxtextarea;
/** /**
* An abstract implementation of the * An abstract implementation of the
* {@link org.fife.ui.rsyntaxtextarea.TokenMaker} interface. It should * {@link org.fife.ui.rsyntaxtextarea.TokenMaker} interface. It should be
* be overridden for every language for which you want to provide * overridden for every language for which you want to provide syntax
* syntax highlighting. * highlighting.
* <p> * <p>
* *
* @see Token * @see Token
@@ -19,34 +19,33 @@ package org.fife.ui.rsyntaxtextarea;
* @version 0.2 * @version 0.2
*/ */
public abstract class AbstractTokenMaker extends TokenMakerBase { public abstract class AbstractTokenMaker extends TokenMakerBase {
/** /**
* Hash table of words to highlight and what token type they are. * Hash table of words to highlight and what token type they are. The keys are
* The keys are the words to highlight, and their values are the * the words to highlight, and their values are the token types, for example,
* token types, for example, <code>Token.RESERVED_WORD</code> or * <code>Token.RESERVED_WORD</code> or <code>Token.FUNCTION</code>.
* <code>Token.FUNCTION</code>.
*/ */
protected TokenMap wordsToHighlight; protected TokenMap wordsToHighlight;
/** /**
* Constructor. * Constructor.
*/ */
public AbstractTokenMaker() { public AbstractTokenMaker() {
wordsToHighlight = getWordsToHighlight(); wordsToHighlight = getWordsToHighlight();
} }
/** /**
* Returns the words to highlight for this programming language. * Returns the words to highlight for this programming language.
* *
* @return A <code>TokenMap</code> containing the words to highlight for * @return A <code>TokenMap</code> containing the words to highlight for this
* this programming language. * programming language.
*/ */
public abstract TokenMap getWordsToHighlight(); public abstract TokenMap getWordsToHighlight();
/** /**
* Removes the token last added from the linked list of tokens. The * Removes the token last added from the linked list of tokens. The programmer
* programmer should never have to call this directly; it can be called * should never have to call this directly; it can be called by subclasses of
* by subclasses of <code>TokenMaker</code> if necessary. * <code>TokenMaker</code> if necessary.
*/ */
public void removeLastToken() { public void removeLastToken() {
if (previousToken == null) { if (previousToken == null) {
@@ -18,15 +18,14 @@ import java.util.Set;
* @version 1.0 * @version 1.0
*/ */
public abstract class AbstractTokenMakerFactory extends TokenMakerFactory { public abstract class AbstractTokenMakerFactory extends TokenMakerFactory {
/** /**
* A mapping from keys to the names of {@link TokenMaker} implementation * A mapping from keys to the names of {@link TokenMaker} implementation class
* class names. When {@link #getTokenMaker(String)} is called with a key * names. When {@link #getTokenMaker(String)} is called with a key defined in
* defined in this map, a <code>TokenMaker</code> of the corresponding type * this map, a <code>TokenMaker</code> of the corresponding type is returned.
* is returned.
*/ */
private Map<String, Object> tokenMakerMap; private Map<String, Object> tokenMakerMap;
/** /**
* Constructor. * Constructor.
*/ */
@@ -34,14 +33,13 @@ public abstract class AbstractTokenMakerFactory extends TokenMakerFactory {
tokenMakerMap = new HashMap<String, Object>(); tokenMakerMap = new HashMap<String, Object>();
initTokenMakerMap(); initTokenMakerMap();
} }
/** /**
* Returns a {@link TokenMaker} for the specified key. * Returns a {@link TokenMaker} for the specified key.
* *
* @param key * @param key The key.
* The key. * @return The corresponding <code>TokenMaker</code>, or <code>null</code> if
* @return The corresponding <code>TokenMaker</code>, or <code>null</code> * none matches the specified key.
* if none matches the specified key.
*/ */
@Override @Override
protected TokenMaker getTokenMakerImpl(String key) { protected TokenMaker getTokenMakerImpl(String key) {
@@ -57,18 +55,18 @@ public abstract class AbstractTokenMakerFactory extends TokenMakerFactory {
} }
return null; return null;
} }
/** /**
* Populates the mapping from keys to instances of * Populates the mapping from keys to instances of
* <code>TokenMakerCreator</code>s. Subclasses should override this method * <code>TokenMakerCreator</code>s. Subclasses should override this method and
* and call one of the <code>putMapping</code> overloads to register * call one of the <code>putMapping</code> overloads to register
* {@link TokenMaker}s for syntax constants. * {@link TokenMaker}s for syntax constants.
* *
* @see #putMapping(String, String) * @see #putMapping(String, String)
* @see #putMapping(String, String, ClassLoader) * @see #putMapping(String, String, ClassLoader)
*/ */
protected abstract void initTokenMakerMap(); protected abstract void initTokenMakerMap();
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -76,50 +74,45 @@ public abstract class AbstractTokenMakerFactory extends TokenMakerFactory {
public Set<String> keySet() { public Set<String> keySet() {
return tokenMakerMap.keySet(); return tokenMakerMap.keySet();
} }
/** /**
* Adds a mapping from a key to a <code>TokenMaker</code> implementation * Adds a mapping from a key to a <code>TokenMaker</code> implementation class
* class name. * name.
* *
* @param key * @param key The key.
* The key. * @param className The <code>TokenMaker</code> class name.
* @param className
* The <code>TokenMaker</code> class name.
* @see #putMapping(String, String, ClassLoader) * @see #putMapping(String, String, ClassLoader)
*/ */
public void putMapping(String key, String className) { public void putMapping(String key, String className) {
putMapping(key, className, null); putMapping(key, className, null);
} }
/** /**
* Adds a mapping from a key to a <code>TokenMaker</code> implementation * Adds a mapping from a key to a <code>TokenMaker</code> implementation class
* class name. * name.
* *
* @param key * @param key The key.
* The key. * @param className The <code>TokenMaker</code> class name.
* @param className * @param cl The class loader to use when loading the class.
* The <code>TokenMaker</code> class name.
* @param cl
* The class loader to use when loading the class.
* @see #putMapping(String, String) * @see #putMapping(String, String)
*/ */
public void putMapping(String key, String className, ClassLoader cl) { public void putMapping(String key, String className, ClassLoader cl) {
tokenMakerMap.put(key, new TokenMakerCreator(className, cl)); tokenMakerMap.put(key, new TokenMakerCreator(className, cl));
} }
/** /**
* Wrapper that handles the creation of TokenMaker instances. * Wrapper that handles the creation of TokenMaker instances.
*/ */
private static class TokenMakerCreator { private static class TokenMakerCreator {
private String className; private String className;
private ClassLoader cl; private ClassLoader cl;
public TokenMakerCreator(String className, ClassLoader cl) { public TokenMakerCreator(String className, ClassLoader cl) {
this.className = className; this.className = className;
this.cl = cl != null ? cl : getClass().getClassLoader(); this.cl = cl != null ? cl : getClass().getClassLoader();
} }
public TokenMaker create() throws Exception { public TokenMaker create() throws Exception {
return (TokenMaker) Class.forName(className, true, cl).newInstance(); return (TokenMaker) Class.forName(className, true, cl).newInstance();
} }
@@ -17,44 +17,39 @@ import java.util.EventObject;
* @version 1.0 * @version 1.0
*/ */
public class ActiveLineRangeEvent extends EventObject { public class ActiveLineRangeEvent extends EventObject {
private int min; private int min;
private int max; private int max;
/** /**
* Constructor. * Constructor.
* *
* @param source * @param source The text area.
* The text area. * @param min The first line in the active line range, or <code>-1</code> if
* @param min * the line range is being cleared.
* The first line in the active line range, or * @param max The last line in the active line range, or <code>-1</code> if
* <code>-1</code> if the line range is being cleared. * the line range is being cleared.
* @param max
* The last line in the active line range, or
* <code>-1</code> if the line range is being cleared.
*/ */
public ActiveLineRangeEvent(RSyntaxTextArea source, int min, int max) { public ActiveLineRangeEvent(RSyntaxTextArea source, int min, int max) {
super(source); super(source);
this.min = min; this.min = min;
this.max = max; this.max = max;
} }
/** /**
* Returns the last line in the active line range. * Returns the last line in the active line range.
* *
* @return The last line, or <code>-1</code> if the range is being * @return The last line, or <code>-1</code> if the range is being cleared.
* cleared.
* @see #getMin() * @see #getMin()
*/ */
public int getMax() { public int getMax() {
return max; return max;
} }
/** /**
* Returns the first line in the active line range. * Returns the first line in the active line range.
* *
* @return The first line, or <code>-1</code> if the range is being * @return The first line, or <code>-1</code> if the range is being cleared.
* cleared.
* @see #getMax() * @see #getMax()
*/ */
public int getMin() { public int getMin() {
@@ -13,29 +13,27 @@ import java.util.EventListener;
* Listens for "active line range" events from an <code>RSyntaxTextArea</code>. * Listens for "active line range" events from an <code>RSyntaxTextArea</code>.
* If a text area contains some semantic knowledge of the programming language * If a text area contains some semantic knowledge of the programming language
* being edited, it may broadcast {@link ActiveLineRangeEvent}s whenever the * being edited, it may broadcast {@link ActiveLineRangeEvent}s whenever the
* caret moves into a new "block" of code. Listeners can listen for these * caret moves into a new "block" of code. Listeners can listen for these events
* events and respond accordingly. * and respond accordingly.
* <p> * <p>
* *
* See the <code>RSTALanguageSupport</code> project at * See the <code>RSTALanguageSupport</code> project at
* <a href="http://fifesoft.com">http://fifesoft.com</a> for some * <a href="http://fifesoft.com">http://fifesoft.com</a> for some
* <code>LanguageSupport</code> implementations that may broadcast these * <code>LanguageSupport</code> implementations that may broadcast these events.
* events. Note that if an RSTA/LanguageSupport does not support broadcasting * Note that if an RSTA/LanguageSupport does not support broadcasting these
* these events, the listener will simply never receive any notifications. * events, the listener will simply never receive any notifications.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public interface ActiveLineRangeListener extends EventListener { public interface ActiveLineRangeListener extends EventListener {
/** /**
* Called whenever the "active line range" changes. * Called whenever the "active line range" changes.
* *
* @param e * @param e Information about the line range change. If there is no longer an
* Information about the line range change. If there is no longer * "active line range," the "minimum" and "maximum" line values should
* an "active line range," the "minimum" and "maximum" line * both be <code>-1</code>.
* values
* should both be <code>-1</code>.
*/ */
void activeLineRangeChanged(ActiveLineRangeEvent e); void activeLineRangeChanged(ActiveLineRangeEvent e);
} }
@@ -13,14 +13,14 @@ import javax.swing.text.Caret;
import org.fife.ui.rtextarea.SmartHighlightPainter; import org.fife.ui.rtextarea.SmartHighlightPainter;
/** /**
* The default implementation of {@link OccurrenceMarker}. It goes through * The default implementation of {@link OccurrenceMarker}. It goes through the
* the document and marks all instances of the specified token. * document and marks all instances of the specified token.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
class DefaultOccurrenceMarker implements OccurrenceMarker { class DefaultOccurrenceMarker implements OccurrenceMarker {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -45,7 +45,7 @@ class DefaultOccurrenceMarker implements OccurrenceMarker {
} }
return t; return t;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -53,7 +53,7 @@ class DefaultOccurrenceMarker implements OccurrenceMarker {
public boolean isValidType(RSyntaxTextArea textArea, Token t) { public boolean isValidType(RSyntaxTextArea textArea, Token t) {
return textArea.getMarkOccurrencesOfTokenType(t.getType()); return textArea.getMarkOccurrencesOfTokenType(t.getType());
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -61,21 +61,18 @@ class DefaultOccurrenceMarker implements OccurrenceMarker {
public void markOccurrences(RSyntaxDocument doc, Token t, RSyntaxTextAreaHighlighter h, SmartHighlightPainter p) { public void markOccurrences(RSyntaxDocument doc, Token t, RSyntaxTextAreaHighlighter h, SmartHighlightPainter p) {
markOccurrencesOfToken(doc, t, h, p); markOccurrencesOfToken(doc, t, h, p);
} }
/** /**
* Highlights all instances of tokens identical to <code>t</code> in the * Highlights all instances of tokens identical to <code>t</code> in the
* specified document. * specified document.
* *
* @param doc * @param doc The document.
* The document. * @param t The document whose relevant occurrences should be marked.
* @param t * @param h The highlighter to add the highlights to.
* The document whose relevant occurrences should be marked. * @param p The painter for the highlights.
* @param h
* The highlighter to add the highlights to.
* @param p
* The painter for the highlights.
*/ */
public static final void markOccurrencesOfToken(RSyntaxDocument doc, Token t, RSyntaxTextAreaHighlighter h, SmartHighlightPainter p) { public static final void markOccurrencesOfToken(RSyntaxDocument doc, Token t, RSyntaxTextAreaHighlighter h,
SmartHighlightPainter p) {
char[] lexeme = t.getLexeme().toCharArray(); char[] lexeme = t.getLexeme().toCharArray();
int type = t.getType(); int type = t.getType();
int lineCount = doc.getDefaultRootElement().getElementCount(); int lineCount = doc.getDefaultRootElement().getElementCount();
@@ -10,46 +10,43 @@ import javax.swing.text.Segment;
/** /**
* This class generates tokens for a {@link TokenMaker}. This class is here * This class generates tokens for a {@link TokenMaker}. This class is here
* because it reuses tokens when they aren't needed anymore to prevent * because it reuses tokens when they aren't needed anymore to prevent This
* This class doesn't actually create new tokens every time * class doesn't actually create new tokens every time <code>createToken</code>
* <code>createToken</code> is called. Instead, it internally keeps a stack of * is called. Instead, it internally keeps a stack of available already-created
* available already-created tokens. When more tokens are needed to properly * tokens. When more tokens are needed to properly display a line, more tokens
* display a line, more tokens are added to the available stack. This saves * are added to the available stack. This saves from needless repetitive memory
* from needless repetitive memory allocation. However, it makes it IMPERATIVE * allocation. However, it makes it IMPERATIVE that users call
* that users call <code>resetTokenList</code> when creating a new token list so * <code>resetTokenList</code> when creating a new token list so that the token
* that the token maker can keep an accurate list of available tokens. * maker can keep an accurate list of available tokens.
* <p> * <p>
* *
* NOTE: This class should only be used by {@link TokenMaker}; nobody else * NOTE: This class should only be used by {@link TokenMaker}; nobody else needs
* needs it! * it!
* *
* @author Robert Futrell * @author Robert Futrell
* @version 0.1 * @version 0.1
*/ */
class DefaultTokenFactory implements TokenFactory { class DefaultTokenFactory implements TokenFactory {
private int size; private int size;
private int increment; private int increment;
private TokenImpl[] tokenList; private TokenImpl[] tokenList;
private int currentFreeToken; private int currentFreeToken;
protected static final int DEFAULT_START_SIZE = 30; protected static final int DEFAULT_START_SIZE = 30;
protected static final int DEFAULT_INCREMENT = 10; protected static final int DEFAULT_INCREMENT = 10;
/** /**
* Constructor. * Constructor.
*/ */
DefaultTokenFactory() { DefaultTokenFactory() {
this(DEFAULT_START_SIZE, DEFAULT_INCREMENT); this(DEFAULT_START_SIZE, DEFAULT_INCREMENT);
} }
/** /**
* Constructor. * Constructor.
* *
* @param size * @param size The initial number of tokens in this factory.
* The initial number of tokens in this factory. * @param increment How many tokens to increment by when the stack gets empty.
* @param increment
* How many tokens to increment by when the stack gets
* empty.
*/ */
DefaultTokenFactory(int size, int increment) { DefaultTokenFactory(int size, int increment) {
this.size = size; this.size = size;
@@ -61,10 +58,10 @@ class DefaultTokenFactory implements TokenFactory {
tokenList[i] = new TokenImpl(); tokenList[i] = new TokenImpl();
} }
} }
/** /**
* Adds tokens to the internal token list. This is called whenever a * Adds tokens to the internal token list. This is called whenever a request is
* request is made and no more tokens are available. * made and no more tokens are available.
*/ */
private void augmentTokenList() { private void augmentTokenList() {
TokenImpl[] temp = new TokenImpl[size + increment]; TokenImpl[] temp = new TokenImpl[size + increment];
@@ -76,37 +73,35 @@ class DefaultTokenFactory implements TokenFactory {
} }
// System.err.println("... size up to: " + size); // System.err.println("... size up to: " + size);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public TokenImpl createToken() { public TokenImpl createToken() {
TokenImpl token = tokenList[currentFreeToken]; TokenImpl token = tokenList[currentFreeToken];
token.text = null; token.reset();
token.setType(Token.NULL); if (++currentFreeToken == size) {
token.setOffset(-1);
token.setNextToken(null);
currentFreeToken++;
if (currentFreeToken == size) {
augmentTokenList(); augmentTokenList();
} }
return token; return token;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public TokenImpl createToken(final Segment line, final int beg, final int end, final int startOffset, final int type) { public TokenImpl createToken(final Segment line, final int beg, final int end, final int startOffset,
final int type) {
return createToken(line.array, beg, end, startOffset, type); return createToken(line.array, beg, end, startOffset, type);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public TokenImpl createToken(final char[] line, final int beg, final int end, final int startOffset, final int type) { public TokenImpl createToken(final char[] line, final int beg, final int end, final int startOffset,
final int type) {
TokenImpl token = tokenList[currentFreeToken]; TokenImpl token = tokenList[currentFreeToken];
token.set(line, beg, end, startOffset, type); token.set(line, beg, end, startOffset, type);
currentFreeToken++; currentFreeToken++;
@@ -115,11 +110,11 @@ class DefaultTokenFactory implements TokenFactory {
} }
return token; return token;
} }
/** /**
* Resets the state of this token maker. This method should be called * Resets the state of this token maker. This method should be called by the
* by the <code>TokenMaker</code> every time a token list is generated for * <code>TokenMaker</code> every time a token list is generated for a new line
* a new line so the tokens can be reused. * so the tokens can be reused.
*/ */
@Override @Override
public void resetAllTokens() { public void resetAllTokens() {
@@ -15,7 +15,7 @@ package org.fife.ui.rsyntaxtextarea;
* @version 1.0 * @version 1.0
*/ */
class DefaultTokenMakerFactory extends AbstractTokenMakerFactory implements SyntaxConstants { class DefaultTokenMakerFactory extends AbstractTokenMakerFactory implements SyntaxConstants {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -20,22 +20,22 @@ import javax.swing.text.TabExpander;
* @version 1.0 * @version 1.0
*/ */
class DefaultTokenPainter implements TokenPainter { class DefaultTokenPainter implements TokenPainter {
/** /**
* Rectangle used for filling token backgrounds. * Rectangle used for filling token backgrounds.
*/ */
private Rectangle2D.Float bgRect; private Rectangle2D.Float bgRect;
/** /**
* Micro-optimization; buffer used to compute tab width. If the width is * Micro-optimization; buffer used to compute tab width. If the width is correct
* correct it's not re-allocated, to prevent lots of very small garbage. * it's not re-allocated, to prevent lots of very small garbage. Only used when
* Only used when painting tab lines. * painting tab lines.
*/ */
private static char[] tabBuf; private static char[] tabBuf;
DefaultTokenPainter() { DefaultTokenPainter() {
bgRect = new Rectangle2D.Float(); bgRect = new Rectangle2D.Float();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -43,57 +43,51 @@ class DefaultTokenPainter implements TokenPainter {
public final float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e) { public final float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e) {
return paint(token, g, x, y, host, e, 0); return paint(token, g, x, y, host, e, 0);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart) { public float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e,
float clipStart) {
return paintImpl(token, g, x, y, host, e, clipStart, false, false); return paintImpl(token, g, x, y, host, e, clipStart, false, false);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart, boolean paintBG) { public float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e,
float clipStart, boolean paintBG) {
return paintImpl(token, g, x, y, host, e, clipStart, !paintBG, false); return paintImpl(token, g, x, y, host, e, clipStart, !paintBG, false);
} }
/** /**
* Paints the background of a token. * Paints the background of a token.
* *
* @param x * @param x The x-coordinate of the token.
* The x-coordinate of the token. * @param y The y-coordinate of the token.
* @param y * @param width The width of the token (actually, the width of the part of
* The y-coordinate of the token. * the token to paint).
* @param width * @param height The height of the token.
* The width of the token (actually, the width of the part of * @param g The graphics context with which to paint.
* the token to paint). * @param fontAscent The ascent of the token's font.
* @param height * @param host The text area.
* The height of the token. * @param color The color with which to paint.
* @param g
* The graphics context with which to paint.
* @param fontAscent
* The ascent of the token's font.
* @param host
* The text area.
* @param color
* The color with which to paint.
*/ */
protected void paintBackground(float x, float y, float width, float height, Graphics2D g, int fontAscent, RSyntaxTextArea host, protected void paintBackground(float x, float y, float width, float height, Graphics2D g, int fontAscent,
Color color) { RSyntaxTextArea host, Color color) {
g.setColor(color); g.setColor(color);
bgRect.setRect(x, y - fontAscent, width, height); bgRect.setRect(x, y - fontAscent, width, height);
// g.fill(bgRect); // g.fill(bgRect);
g.fillRect((int) x, (int) (y - fontAscent), (int) width, (int) height); g.fillRect((int) x, (int) (y - fontAscent), (int) width, (int) height);
} }
/** /**
* Does the dirty-work of actually painting the token. * Does the dirty-work of actually painting the token.
*/ */
protected float paintImpl(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart, protected float paintImpl(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e,
boolean selected, boolean useSTC) { float clipStart, boolean selected, boolean useSTC) {
int origX = (int) x; int origX = (int) x;
int textOffs = token.getTextOffset(); int textOffs = token.getTextOffset();
char[] text = token.getTextArray(); char[] text = token.getTextArray();
@@ -107,22 +101,22 @@ class DefaultTokenPainter implements TokenPainter {
FontMetrics fm = host.getFontMetricsForTokenType(token.getType()); FontMetrics fm = host.getFontMetricsForTokenType(token.getType());
for (int i = textOffs; i < end; i++) { for (int i = textOffs; i < end; i++) {
switch (text[i]) { switch (text[i]) {
case '\t': case '\t':
nextX = e.nextTabStop(x + fm.charsWidth(text, flushIndex, flushLen), 0); nextX = e.nextTabStop(x + fm.charsWidth(text, flushIndex, flushLen), 0);
if (bg != null) { if (bg != null) {
paintBackground(x, y, nextX - x, fm.getHeight(), g, fm.getAscent(), host, bg); paintBackground(x, y, nextX - x, fm.getHeight(), g, fm.getAscent(), host, bg);
} }
if (flushLen > 0) { if (flushLen > 0) {
g.setColor(fg); g.setColor(fg);
g.drawChars(text, flushIndex, flushLen, (int) x, (int) y); g.drawChars(text, flushIndex, flushLen, (int) x, (int) y);
flushLen = 0; flushLen = 0;
} }
flushIndex = i + 1; flushIndex = i + 1;
x = nextX; x = nextX;
break; break;
default: default:
flushLen += 1; flushLen += 1;
break; break;
} }
} }
nextX = x + fm.charsWidth(text, flushIndex, flushLen); nextX = x + fm.charsWidth(text, flushIndex, flushLen);
@@ -152,48 +146,43 @@ class DefaultTokenPainter implements TokenPainter {
} }
return nextX; return nextX;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public float paintSelected(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, boolean useSTC) { public float paintSelected(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e,
boolean useSTC) {
return paintSelected(token, g, x, y, host, e, 0, useSTC); return paintSelected(token, g, x, y, host, e, 0, useSTC);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public float paintSelected(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart, public float paintSelected(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e,
boolean useSTC) { float clipStart, boolean useSTC) {
return paintImpl(token, g, x, y, host, e, clipStart, true, useSTC); return paintImpl(token, g, x, y, host, e, clipStart, true, useSTC);
} }
/** /**
* Paints dotted "tab" lines; that is, lines that show where your caret * Paints dotted "tab" lines; that is, lines that show where your caret would go
* would go to on the line if you hit "tab". This visual effect is usually * to on the line if you hit "tab". This visual effect is usually done in the
* done in the leading whitespace token(s) of lines. * leading whitespace token(s) of lines.
* *
* @param token * @param token The token to render.
* The token to render. * @param x The starting x-offset of this token. It is assumed that this is
* @param x * the left margin of the text area (may be non-zero due to
* The starting x-offset of this token. It is assumed that this * insets), since tab lines are only painted for leading
* is the left margin of the text area (may be non-zero due to * whitespace.
* insets), since tab lines are only painted for leading * @param y The baseline where this token was painted.
* whitespace. * @param endX The ending x-offset of this token.
* @param y * @param g The graphics context.
* The baseline where this token was painted. * @param e Used to expand tabs.
* @param endX * @param host The text area.
* The ending x-offset of this token.
* @param g
* The graphics context.
* @param e
* Used to expand tabs.
* @param host
* The text area.
*/ */
protected void paintTabLines(Token token, int x, int y, int endX, Graphics2D g, TabExpander e, RSyntaxTextArea host) { protected void paintTabLines(Token token, int x, int y, int endX, Graphics2D g, TabExpander e,
RSyntaxTextArea host) {
// We allow tab lines to be painted in more than just Token.WHITESPACE, // We allow tab lines to be painted in more than just Token.WHITESPACE,
// i.e. for MLC's and Token.IDENTIFIERS (for TokenMakers that return // i.e. for MLC's and Token.IDENTIFIERS (for TokenMakers that return
// whitespace as identifiers for performance). But we only paint tab // whitespace as identifiers for performance). But we only paint tab
@@ -13,30 +13,27 @@ package org.fife.ui.rsyntaxtextarea;
* @version 1.0 * @version 1.0
*/ */
public class DocumentRange implements Comparable<DocumentRange> { public class DocumentRange implements Comparable<DocumentRange> {
private int startOffs; private int startOffs;
private int endOffs; private int endOffs;
/** /**
* Constructor. * Constructor.
* *
* @param startOffs * @param startOffs The starting offset in the document, inclusive.
* The starting offset in the document, inclusive. * @param endOffs The ending offset in the document, exclusive.
* @param endOffs * @throws IllegalArgumentException If <code>endOffs</code> is less than
* The ending offset in the document, exclusive. * <code>startOffs</code>, or either argument
* @throws IllegalArgumentException * is less than zero.
* If <code>endOffs</code> is less than
* <code>startOffs</code>, or either argument is less than zero.
*/ */
public DocumentRange(int startOffs, int endOffs) { public DocumentRange(int startOffs, int endOffs) {
set(startOffs, endOffs); set(startOffs, endOffs);
} }
/** /**
* Compares this document range to another. * Compares this document range to another.
* *
* @param other * @param other Another document range.
* Another document range.
* @return How the two should be sorted relative to each other. * @return How the two should be sorted relative to each other.
*/ */
@Override @Override
@@ -50,14 +47,13 @@ public class DocumentRange implements Comparable<DocumentRange> {
} }
return endOffs - other.endOffs; return endOffs - other.endOffs;
} }
/** /**
* Returns whether this document range is equal to another one. * Returns whether this document range is equal to another one.
* *
* @param other * @param other Another object, presumably a document range.
* Another object, presumably a document range. * @return Whether <code>other</code> is also a document range, and equal to
* @return Whether <code>other</code> is also a document range, and equal * this one.
* to this one.
*/ */
@Override @Override
public boolean equals(Object other) { public boolean equals(Object other) {
@@ -69,7 +65,7 @@ public class DocumentRange implements Comparable<DocumentRange> {
} }
return false; return false;
} }
/** /**
* Gets the end offset of the range. * Gets the end offset of the range.
* *
@@ -79,7 +75,7 @@ public class DocumentRange implements Comparable<DocumentRange> {
public int getEndOffset() { public int getEndOffset() {
return endOffs; return endOffs;
} }
/** /**
* Gets the starting offset of the range. * Gets the starting offset of the range.
* *
@@ -89,7 +85,7 @@ public class DocumentRange implements Comparable<DocumentRange> {
public int getStartOffset() { public int getStartOffset() {
return startOffs; return startOffs;
} }
/** /**
* Overridden simply as a best practice, since {@link #equals(Object)} is * Overridden simply as a best practice, since {@link #equals(Object)} is
* overridden. * overridden.
@@ -100,29 +96,26 @@ public class DocumentRange implements Comparable<DocumentRange> {
public int hashCode() { public int hashCode() {
return startOffs + endOffs; return startOffs + endOffs;
} }
/** /**
* Returns whether this document range has zero length. This can happen, * Returns whether this document range has zero length. This can happen, for
* for example, with regex searches of forms like * example, with regex searches of forms like <code>"foo|"</code>, where the
* <code>"foo|"</code>, where the right-hand sub-expression matches empty * right-hand sub-expression matches empty strings.
* strings.
* *
* @return Whether this document range has zero length. * @return Whether this document range has zero length.
*/ */
public boolean isZeroLength() { public boolean isZeroLength() {
return startOffs == endOffs; return startOffs == endOffs;
} }
/** /**
* Sets the document range. * Sets the document range.
* *
* @param start * @param start The new start value, inclusive.
* The new start value, inclusive. * @param end The new end value, exclusive.
* @param end * @throws IllegalArgumentException If <code>end</code> is less than
* The new end value, exclusive. * <code>start</code>, or either argument is
* @throws IllegalArgumentException * less than zero.
* If <code>end</code> is less than
* <code>start</code>, or either argument is less than zero.
*/ */
public void set(int start, int end) { public void set(int start, int end) {
if (start < 0 || end < 0) { if (start < 0 || end < 0) {
@@ -134,7 +127,7 @@ public class DocumentRange implements Comparable<DocumentRange> {
this.startOffs = start; this.startOffs = start;
this.endOffs = end; this.endOffs = end;
} }
/** /**
* Returns a string representation of this object. * Returns a string representation of this object.
* *
@@ -144,12 +137,11 @@ public class DocumentRange implements Comparable<DocumentRange> {
public String toString() { public String toString() {
return "[DocumentRange: " + startOffs + "-" + endOffs + "]"; return "[DocumentRange: " + startOffs + "-" + endOffs + "]";
} }
/** /**
* Translates this document range by a given amount. * Translates this document range by a given amount.
* *
* @param amount * @param amount The amount to translate this range by.
* The amount to translate this range by.
* @return This (modified) range. * @return This (modified) range.
*/ */
public DocumentRange translate(int amount) { public DocumentRange translate(int amount) {
+113 -130
View File
@@ -39,16 +39,15 @@ import org.fife.ui.rsyntaxtextarea.parser.TaskTagParser.TaskNotice;
import org.fife.ui.rtextarea.RTextArea; import org.fife.ui.rtextarea.RTextArea;
/** /**
* A component to sit alongside an {@link RSyntaxTextArea} that displays * A component to sit alongside an {@link RSyntaxTextArea} that displays colored
* colored markers for locations of interest (parser errors, marked * markers for locations of interest (parser errors, marked occurrences, etc.).
* occurrences, etc.).
* <p> * <p>
* *
* <code>ErrorStrip</code>s display <code>ParserNotice</code>s from * <code>ErrorStrip</code>s display <code>ParserNotice</code>s from
* {@link Parser}s. Currently, the only way to get lines flagged in this * {@link Parser}s. Currently, the only way to get lines flagged in this
* component is to register a <code>Parser</code> on an RSyntaxTextArea and * component is to register a <code>Parser</code> on an RSyntaxTextArea and
* return <code>ParserNotice</code>s for each line to display an icon for. * return <code>ParserNotice</code>s for each line to display an icon for. The
* The severity of each notice must be at least the threshold set by * severity of each notice must be at least the threshold set by
* {@link #setLevelThreshold(org.fife.ui.rsyntaxtextarea.parser.ParserNotice.Level)} * {@link #setLevelThreshold(org.fife.ui.rsyntaxtextarea.parser.ParserNotice.Level)}
* to be displayed in this error strip. The default threshold is * to be displayed in this error strip. The default threshold is
* {@link org.fife.ui.rsyntaxtextarea.parser.ParserNotice.Level#WARNING}. * {@link org.fife.ui.rsyntaxtextarea.parser.ParserNotice.Level#WARNING}.
@@ -76,7 +75,7 @@ import org.fife.ui.rtextarea.RTextArea;
// are now "empty"). // are now "empty").
// //
public class ErrorStrip extends JPanel { public class ErrorStrip extends JPanel {
/** /**
* The text area. * The text area.
*/ */
@@ -86,23 +85,23 @@ public class ErrorStrip extends JPanel {
*/ */
private transient Listener listener; private transient Listener listener;
/** /**
* Whether "marked occurrences" in the text area should be shown in this * Whether "marked occurrences" in the text area should be shown in this error
* error strip. * strip.
*/ */
private boolean showMarkedOccurrences; private boolean showMarkedOccurrences;
/** /**
* Whether markers for "mark all" highlights should be shown in this * Whether markers for "mark all" highlights should be shown in this error
* error strip. * strip.
*/ */
private boolean showMarkAll; private boolean showMarkAll;
/** /**
* Mapping of colors to brighter colors. This is kept to prevent * Mapping of colors to brighter colors. This is kept to prevent unnecessary
* unnecessary creation of the same Colors over and over. * creation of the same Colors over and over.
*/ */
private Map<Color, Color> brighterColors; private Map<Color, Color> brighterColors;
/** /**
* Only notices of this severity (or worse) will be displayed in this * Only notices of this severity (or worse) will be displayed in this error
* error strip. * strip.
*/ */
private ParserNotice.Level levelThreshold; private ParserNotice.Level levelThreshold;
/** /**
@@ -130,12 +129,11 @@ public class ErrorStrip extends JPanel {
*/ */
private static final int PREFERRED_WIDTH = 14; private static final int PREFERRED_WIDTH = 14;
private static final ResourceBundle MSG = ResourceBundle.getBundle("org.fife.ui.rsyntaxtextarea.ErrorStrip"); private static final ResourceBundle MSG = ResourceBundle.getBundle("org.fife.ui.rsyntaxtextarea.ErrorStrip");
/** /**
* Constructor. * Constructor.
* *
* @param textArea * @param textArea The text area we are examining.
* The text area we are examining.
*/ */
public ErrorStrip(RSyntaxTextArea textArea) { public ErrorStrip(RSyntaxTextArea textArea) {
this.textArea = textArea; this.textArea = textArea;
@@ -150,10 +148,10 @@ public class ErrorStrip extends JPanel {
setCaretMarkerColor(Color.BLACK); setCaretMarkerColor(Color.BLACK);
setMarkerToolTipProvider(null); // Install default setMarkerToolTipProvider(null); // Install default
} }
/** /**
* Overridden so we only start listening for parser notices when this * Overridden so we only start listening for parser notices when this component
* component (and presumably the text area) are visible. * (and presumably the text area) are visible.
*/ */
@Override @Override
public void addNotify() { public void addNotify() {
@@ -165,7 +163,7 @@ public class ErrorStrip extends JPanel {
textArea.addPropertyChangeListener(RSyntaxTextArea.MARK_ALL_OCCURRENCES_CHANGED_PROPERTY, listener); textArea.addPropertyChangeListener(RSyntaxTextArea.MARK_ALL_OCCURRENCES_CHANGED_PROPERTY, listener);
refreshMarkers(); refreshMarkers();
} }
/** /**
* Manually manages layout since this component uses no layout manager. * Manually manages layout since this component uses no layout manager.
*/ */
@@ -177,12 +175,11 @@ public class ErrorStrip extends JPanel {
} }
listener.caretUpdate(null); // Force recalculation of caret line pos listener.caretUpdate(null); // Force recalculation of caret line pos
} }
/** /**
* Returns a "brighter" color. * Returns a "brighter" color.
* *
* @param c * @param c The color.
* The color.
* @return A brighter color. * @return A brighter color.
*/ */
private Color getBrighterColor(Color c) { private Color getBrighterColor(Color c) {
@@ -201,7 +198,7 @@ public class ErrorStrip extends JPanel {
} }
return brighter; return brighter;
} }
/** /**
* returns the color to use when painting the caret marker. * returns the color to use when painting the caret marker.
* *
@@ -211,7 +208,7 @@ public class ErrorStrip extends JPanel {
public Color getCaretMarkerColor() { public Color getCaretMarkerColor() {
return caretMarkerColor; return caretMarkerColor;
} }
/** /**
* Returns whether the caret's position should be drawn. * Returns whether the caret's position should be drawn.
* *
@@ -221,7 +218,7 @@ public class ErrorStrip extends JPanel {
public boolean getFollowCaret() { public boolean getFollowCaret() {
return followCaret; return followCaret;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -230,11 +227,11 @@ public class ErrorStrip extends JPanel {
int height = textArea.getPreferredScrollableViewportSize().height; int height = textArea.getPreferredScrollableViewportSize().height;
return new Dimension(PREFERRED_WIDTH, height); return new Dimension(PREFERRED_WIDTH, height);
} }
/** /**
* Returns the minimum severity a parser notice must be for it to be * Returns the minimum severity a parser notice must be for it to be displayed
* displayed in this error strip. This will be one of the constants * in this error strip. This will be one of the constants defined in the
* defined in the <code>ParserNotice</code> class. * <code>ParserNotice</code> class.
* *
* @return The minimum severity. * @return The minimum severity.
* @see #setLevelThreshold(org.fife.ui.rsyntaxtextarea.parser.ParserNotice.Level) * @see #setLevelThreshold(org.fife.ui.rsyntaxtextarea.parser.ParserNotice.Level)
@@ -242,7 +239,7 @@ public class ErrorStrip extends JPanel {
public ParserNotice.Level getLevelThreshold() { public ParserNotice.Level getLevelThreshold() {
return levelThreshold; return levelThreshold;
} }
/** /**
* Returns whether "mark all" highlights are shown in this error strip. * Returns whether "mark all" highlights are shown in this error strip.
* *
@@ -252,7 +249,7 @@ public class ErrorStrip extends JPanel {
public boolean getShowMarkAll() { public boolean getShowMarkAll() {
return showMarkAll; return showMarkAll;
} }
/** /**
* Returns whether marked occurrences are shown in this error strip. * Returns whether marked occurrences are shown in this error strip.
* *
@@ -262,7 +259,7 @@ public class ErrorStrip extends JPanel {
public boolean getShowMarkedOccurrences() { public boolean getShowMarkedOccurrences() {
return showMarkedOccurrences; return showMarkedOccurrences;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -276,13 +273,12 @@ public class ErrorStrip extends JPanel {
} }
return text; return text;
} }
/** /**
* Returns the y-offset in this component corresponding to a line in the * Returns the y-offset in this component corresponding to a line in the text
* text component. * component.
* *
* @param line * @param line The line.
* The line.
* @return The y-offset. * @return The y-offset.
* @see #yToLine(int) * @see #yToLine(int)
*/ */
@@ -291,12 +287,11 @@ public class ErrorStrip extends JPanel {
float lineCount = textArea.getLineCount(); float lineCount = textArea.getLineCount();
return (int) (((line - 1) / (lineCount - 1)) * (h - 2)); return (int) (((line - 1) / (lineCount - 1)) * (h - 2));
} }
/** /**
* Overridden to (possibly) draw the caret's position. * Overridden to (possibly) draw the caret's position.
* *
* @param g * @param g The graphics context.
* The graphics context.
*/ */
@Override @Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
@@ -306,12 +301,11 @@ public class ErrorStrip extends JPanel {
g.fillRect(0, caretLineY, getWidth(), 2); g.fillRect(0, caretLineY, getWidth(), 2);
} }
} }
/** /**
* Returns a possibly brighter component for a color. * Returns a possibly brighter component for a color.
* *
* @param i * @param i An RGB component for a color (0-255).
* An RGB component for a color (0-255).
* @return A possibly brighter value for the component. * @return A possibly brighter value for the component.
*/ */
private static int possiblyBrighter(int i) { private static int possiblyBrighter(int i) {
@@ -320,7 +314,7 @@ public class ErrorStrip extends JPanel {
} }
return i; return i;
} }
/** /**
* Refreshes the markers displayed in this error strip. * Refreshes the markers displayed in this error strip.
*/ */
@@ -354,16 +348,13 @@ public class ErrorStrip extends JPanel {
revalidate(); revalidate();
repaint(); repaint();
} }
/** /**
* Adds markers for a list of ranges in the document. * Adds markers for a list of ranges in the document.
* *
* @param ranges * @param ranges The list of ranges in the document.
* The list of ranges in the document. * @param markerMap A mapping from line number to <code>Marker</code>.
* @param markerMap * @param color The color to use for the markers.
* A mapping from line number to <code>Marker</code>.
* @param color
* The color to use for the markers.
*/ */
private void addMarkersForRanges(List<DocumentRange> ranges, Map<Integer, Marker> markerMap, Color color) { private void addMarkersForRanges(List<DocumentRange> ranges, Map<Integer, Marker> markerMap, Color color) {
for (DocumentRange range : ranges) { for (DocumentRange range : ranges) {
@@ -388,7 +379,7 @@ public class ErrorStrip extends JPanel {
} }
} }
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -401,12 +392,11 @@ public class ErrorStrip extends JPanel {
textArea.removePropertyChangeListener(RSyntaxTextArea.MARKED_OCCURRENCES_CHANGED_PROPERTY, listener); textArea.removePropertyChangeListener(RSyntaxTextArea.MARKED_OCCURRENCES_CHANGED_PROPERTY, listener);
textArea.removePropertyChangeListener(RSyntaxTextArea.MARK_ALL_OCCURRENCES_CHANGED_PROPERTY, listener); textArea.removePropertyChangeListener(RSyntaxTextArea.MARK_ALL_OCCURRENCES_CHANGED_PROPERTY, listener);
} }
/** /**
* Sets the color to use when painting the caret marker. * Sets the color to use when painting the caret marker.
* *
* @param color * @param color The new caret marker color.
* The new caret marker color.
* @see #getCaretMarkerColor() * @see #getCaretMarkerColor()
*/ */
public void setCaretMarkerColor(Color color) { public void setCaretMarkerColor(Color color) {
@@ -415,12 +405,11 @@ public class ErrorStrip extends JPanel {
listener.caretUpdate(null); // Force repaint listener.caretUpdate(null); // Force repaint
} }
} }
/** /**
* Toggles whether the caret's current location should be drawn. * Toggles whether the caret's current location should be drawn.
* *
* @param follow * @param follow Whether the caret's current location should be followed.
* Whether the caret's current location should be followed.
* @see #getFollowCaret() * @see #getFollowCaret()
*/ */
public void setFollowCaret(boolean follow) { public void setFollowCaret(boolean follow) {
@@ -434,15 +423,14 @@ public class ErrorStrip extends JPanel {
listener.caretUpdate(null); // Possibly repaint listener.caretUpdate(null); // Possibly repaint
} }
} }
/** /**
* Sets the minimum severity a parser notice must be for it to be displayed * Sets the minimum severity a parser notice must be for it to be displayed in
* in this error strip. This should be one of the constants defined in * this error strip. This should be one of the constants defined in the
* the <code>ParserNotice</code> class. The default value is * <code>ParserNotice</code> class. The default value is
* {@link org.fife.ui.rsyntaxtextarea.parser.ParserNotice.Level#WARNING}. * {@link org.fife.ui.rsyntaxtextarea.parser.ParserNotice.Level#WARNING}.
* *
* @param level * @param level The new severity threshold.
* The new severity threshold.
* @see #getLevelThreshold() * @see #getLevelThreshold()
* @see ParserNotice * @see ParserNotice
*/ */
@@ -452,25 +440,23 @@ public class ErrorStrip extends JPanel {
refreshMarkers(); refreshMarkers();
} }
} }
/** /**
* Sets the provider of tool tips for markers in this error strip. * Sets the provider of tool tips for markers in this error strip. Applications
* Applications can use this method to control the content and format of * can use this method to control the content and format of the tool tip
* the tool tip descriptions of line markers. * descriptions of line markers.
* *
* @param provider * @param provider The provider. If this is <code>null</code>, a default
* The provider. If this is <code>null</code>, a default * implementation will be used.
* implementation will be used.
*/ */
public void setMarkerToolTipProvider(ErrorStripMarkerToolTipProvider provider) { public void setMarkerToolTipProvider(ErrorStripMarkerToolTipProvider provider) {
markerToolTipProvider = provider != null ? provider : new DefaultErrorStripMarkerToolTipProvider(); markerToolTipProvider = provider != null ? provider : new DefaultErrorStripMarkerToolTipProvider();
} }
/** /**
* Sets whether "mark all" highlights are shown in this error strip. * Sets whether "mark all" highlights are shown in this error strip.
* *
* @param show * @param show Whether to show markers for "mark all" highlights.
* Whether to show markers for "mark all" highlights.
* @see #getShowMarkAll() * @see #getShowMarkAll()
*/ */
public void setShowMarkAll(boolean show) { public void setShowMarkAll(boolean show) {
@@ -481,12 +467,11 @@ public class ErrorStrip extends JPanel {
} }
} }
} }
/** /**
* Sets whether marked occurrences are shown in this error strip. * Sets whether marked occurrences are shown in this error strip.
* *
* @param show * @param show Whether to show marked occurrences.
* Whether to show marked occurrences.
* @see #getShowMarkedOccurrences() * @see #getShowMarkedOccurrences()
*/ */
public void setShowMarkedOccurrences(boolean show) { public void setShowMarkedOccurrences(boolean show) {
@@ -497,13 +482,12 @@ public class ErrorStrip extends JPanel {
} }
} }
} }
/** /**
* Returns the line in the text area corresponding to a y-offset in this * Returns the line in the text area corresponding to a y-offset in this
* component. * component.
* *
* @param y * @param y The y-offset.
* The y-offset.
* @return The line. * @return The line.
* @see #lineToY(int) * @see #lineToY(int)
*/ */
@@ -516,15 +500,15 @@ public class ErrorStrip extends JPanel {
} }
return line; return line;
} }
/** /**
* The default implementation of the provider of tool tips for markers in * The default implementation of the provider of tool tips for markers in an
* an error strip. * error strip.
* *
* @author predi * @author predi
*/ */
private static class DefaultErrorStripMarkerToolTipProvider implements ErrorStripMarkerToolTipProvider { private static class DefaultErrorStripMarkerToolTipProvider implements ErrorStripMarkerToolTipProvider {
@Override @Override
public String getToolTipText(List<ParserNotice> notices) { public String getToolTipText(List<ParserNotice> notices) {
String text = null; String text = null;
@@ -545,34 +529,33 @@ public class ErrorStrip extends JPanel {
return text; return text;
} }
} }
/** /**
* Returns tool tip text for the markers in an {@link ErrorStrip} that * Returns tool tip text for the markers in an {@link ErrorStrip} that denote
* denote one or more parser notices. * one or more parser notices.
* *
* @author predi * @author predi
*/ */
public interface ErrorStripMarkerToolTipProvider { public interface ErrorStripMarkerToolTipProvider {
/** /**
* Returns the tool tip text for a marker in an <code>ErrorStrip</code> * Returns the tool tip text for a marker in an <code>ErrorStrip</code> that
* that denotes a given list of parser notices. * denotes a given list of parser notices.
* *
* @param notices * @param notices The list of parser notices.
* The list of parser notices. * @return The tool tip text. This may be HTML. Returning <code>null</code> will
* @return The tool tip text. This may be HTML. Returning * result in no tool tip being displayed.
* <code>null</code> will result in no tool tip being displayed.
*/ */
String getToolTipText(List<ParserNotice> notices); String getToolTipText(List<ParserNotice> notices);
} }
/** /**
* Listens for events in the error strip and its markers. * Listens for events in the error strip and its markers.
*/ */
private class Listener extends MouseAdapter implements PropertyChangeListener, CaretListener { private class Listener extends MouseAdapter implements PropertyChangeListener, CaretListener {
private Rectangle visibleRect = new Rectangle(); private Rectangle visibleRect = new Rectangle();
@Override @Override
public void caretUpdate(CaretEvent e) { public void caretUpdate(CaretEvent e) {
if (getFollowCaret()) { if (getFollowCaret()) {
@@ -587,7 +570,7 @@ public class ErrorStrip extends JPanel {
} }
} }
} }
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
Component source = (Component) e.getSource(); Component source = (Component) e.getSource();
@@ -605,7 +588,7 @@ public class ErrorStrip extends JPanel {
} }
} }
} }
@Override @Override
public void propertyChange(PropertyChangeEvent e) { public void propertyChange(PropertyChangeEvent e) {
String propName = e.getPropertyName(); String propName = e.getPropertyName();
@@ -636,30 +619,30 @@ public class ErrorStrip extends JPanel {
} }
} }
} }
/** /**
* A notice that wraps a "marked occurrence" instance. * A notice that wraps a "marked occurrence" instance.
*/ */
private class MarkedOccurrenceNotice implements ParserNotice { private class MarkedOccurrenceNotice implements ParserNotice {
private DocumentRange range; private DocumentRange range;
private Color color; private Color color;
MarkedOccurrenceNotice(DocumentRange range, Color color) { MarkedOccurrenceNotice(DocumentRange range, Color color) {
this.range = range; this.range = range;
this.color = color; this.color = color;
} }
@Override @Override
public int compareTo(ParserNotice other) { public int compareTo(ParserNotice other) {
return 0; // Value doesn't matter return 0; // Value doesn't matter
} }
@Override @Override
public boolean containsPosition(int pos) { public boolean containsPosition(int pos) {
return pos >= range.getStartOffset() && pos < range.getEndOffset(); return pos >= range.getStartOffset() && pos < range.getEndOffset();
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
// FindBugs - Define equals() when defining compareTo() // FindBugs - Define equals() when defining compareTo()
@@ -668,12 +651,12 @@ public class ErrorStrip extends JPanel {
} }
return compareTo((ParserNotice) o) == 0; return compareTo((ParserNotice) o) == 0;
} }
@Override @Override
public Color getColor() { public Color getColor() {
return color; return color;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -681,17 +664,17 @@ public class ErrorStrip extends JPanel {
public boolean getKnowsOffsetAndLength() { public boolean getKnowsOffsetAndLength() {
return true; return true;
} }
@Override @Override
public int getLength() { public int getLength() {
return range.getEndOffset() - range.getStartOffset(); return range.getEndOffset() - range.getStartOffset();
} }
@Override @Override
public Level getLevel() { public Level getLevel() {
return Level.INFO; // Won't matter return Level.INFO; // Won't matter
} }
@Override @Override
public int getLine() { public int getLine() {
try { try {
@@ -700,7 +683,7 @@ public class ErrorStrip extends JPanel {
return 0; return 0;
} }
} }
@Override @Override
public String getMessage() { public String getMessage() {
String text = null; String text = null;
@@ -713,40 +696,40 @@ public class ErrorStrip extends JPanel {
} }
return text; return text;
} }
@Override @Override
public int getOffset() { public int getOffset() {
return range.getStartOffset(); return range.getStartOffset();
} }
@Override @Override
public Parser getParser() { public Parser getParser() {
return null; return null;
} }
@Override @Override
public boolean getShowInEditor() { public boolean getShowInEditor() {
return false; // Value doesn't matter return false; // Value doesn't matter
} }
@Override @Override
public String getToolTipText() { public String getToolTipText() {
return null; return null;
} }
@Override @Override
public int hashCode() { // FindBugs, since we override equals() public int hashCode() { // FindBugs, since we override equals()
return 0; // Value doesn't matter for us. return 0; // Value doesn't matter for us.
} }
} }
/** /**
* A "marker" in this error strip, representing one or more notices. * A "marker" in this error strip, representing one or more notices.
*/ */
private class Marker extends JComponent { private class Marker extends JComponent {
private List<ParserNotice> notices; private List<ParserNotice> notices;
Marker(ParserNotice notice) { Marker(ParserNotice notice) {
notices = new ArrayList<ParserNotice>(1); // Usually just 1 notices = new ArrayList<ParserNotice>(1); // Usually just 1
addNotice(notice); addNotice(notice);
@@ -754,11 +737,11 @@ public class ErrorStrip extends JPanel {
setSize(getPreferredSize()); setSize(getPreferredSize());
ToolTipManager.sharedInstance().registerComponent(this); ToolTipManager.sharedInstance().registerComponent(this);
} }
public void addNotice(ParserNotice notice) { public void addNotice(ParserNotice notice) {
notices.add(notice); notices.add(notice);
} }
public boolean containsMarkedOccurence() { public boolean containsMarkedOccurence() {
boolean result = false; boolean result = false;
for (int i = 0; i < notices.size(); i++) { for (int i = 0; i < notices.size(); i++) {
@@ -769,7 +752,7 @@ public class ErrorStrip extends JPanel {
} }
return result; return result;
} }
public Color getColor() { public Color getColor() {
// Return the color for the highest-level parser. // Return the color for the highest-level parser.
Color c = null; Color c = null;
@@ -782,18 +765,18 @@ public class ErrorStrip extends JPanel {
} }
return c; return c;
} }
@Override @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
int w = PREFERRED_WIDTH - 4; // 2-pixel empty border int w = PREFERRED_WIDTH - 4; // 2-pixel empty border
return new Dimension(w, 5); return new Dimension(w, 5);
} }
@Override @Override
public String getToolTipText() { public String getToolTipText() {
return markerToolTipProvider.getToolTipText(Collections.unmodifiableList(notices)); return markerToolTipProvider.getToolTipText(Collections.unmodifiableList(notices));
} }
protected void mouseClicked(MouseEvent e) { protected void mouseClicked(MouseEvent e) {
ParserNotice pn = notices.get(0); ParserNotice pn = notices.get(0);
int offs = pn.getOffset(); int offs = pn.getOffset();
@@ -812,7 +795,7 @@ public class ErrorStrip extends JPanel {
} }
} }
} }
@Override @Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
// TODO: Give "priorities" and always pick color of a notice with // TODO: Give "priorities" and always pick color of a notice with
@@ -829,14 +812,14 @@ public class ErrorStrip extends JPanel {
g.setColor(borderColor); g.setColor(borderColor);
g.drawRect(0, 0, w - 1, h - 1); g.drawRect(0, 0, w - 1, h - 1);
} }
@Override @Override
public void removeNotify() { public void removeNotify() {
super.removeNotify(); super.removeNotify();
ToolTipManager.sharedInstance().unregisterComponent(this); ToolTipManager.sharedInstance().unregisterComponent(this);
removeMouseListener(listener); removeMouseListener(listener);
} }
public void updateLocation() { public void updateLocation() {
int line = notices.get(0).getLine(); int line = notices.get(0).getLine();
int y = lineToY(line); int y = lineToY(line);
@@ -20,17 +20,16 @@ import java.io.OutputStream;
* @version 1.0 * @version 1.0
*/ */
class FileFileLocation extends FileLocation { class FileFileLocation extends FileLocation {
/** /**
* The file. This may or may not actually exist. * The file. This may or may not actually exist.
*/ */
private File file; private File file;
/** /**
* Constructor. * Constructor.
* *
* @param file * @param file The local file.
* The local file.
*/ */
FileFileLocation(File file) { FileFileLocation(File file) {
try { try {
@@ -40,7 +39,7 @@ class FileFileLocation extends FileLocation {
this.file = file; this.file = file;
} }
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -48,7 +47,7 @@ class FileFileLocation extends FileLocation {
protected long getActualLastModified() { protected long getActualLastModified() {
return file.lastModified(); return file.lastModified();
} }
/** /**
* Returns the full path to the file. * Returns the full path to the file.
* *
@@ -59,7 +58,7 @@ class FileFileLocation extends FileLocation {
public String getFileFullPath() { public String getFileFullPath() {
return file.getAbsolutePath(); return file.getAbsolutePath();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -67,7 +66,7 @@ class FileFileLocation extends FileLocation {
public String getFileName() { public String getFileName() {
return file.getName(); return file.getName();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -75,7 +74,7 @@ class FileFileLocation extends FileLocation {
protected InputStream getInputStream() throws IOException { protected InputStream getInputStream() throws IOException {
return new FileInputStream(file); return new FileInputStream(file);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -83,7 +82,7 @@ class FileFileLocation extends FileLocation {
protected OutputStream getOutputStream() throws IOException { protected OutputStream getOutputStream() throws IOException {
return new FileOutputStream(file); return new FileOutputStream(file);
} }
/** /**
* Always returns <code>true</code>. * Always returns <code>true</code>.
* *
@@ -94,10 +93,10 @@ class FileFileLocation extends FileLocation {
public boolean isLocal() { public boolean isLocal() {
return true; return true;
} }
/** /**
* Since file locations of this type are guaranteed to be local, this * Since file locations of this type are guaranteed to be local, this method
* method returns whether the file exists. * returns whether the file exists.
* *
* @return Whether this local file actually exists. * @return Whether this local file actually exists.
* @see #isLocal() * @see #isLocal()
@@ -14,23 +14,23 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
/** /**
* Holds the location of a local or remote file. This provides a common way * Holds the location of a local or remote file. This provides a common way to
* to read, write, and check properties of both local and remote files. * read, write, and check properties of both local and remote files.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public abstract class FileLocation { public abstract class FileLocation {
/** /**
* Creates a {@link FileLocation} instance for the specified local file. * Creates a {@link FileLocation} instance for the specified local file.
* *
* @param fileFullPath * @param fileFullPath The full path to a local file.
* The full path to a local file.
* @return The file's location. * @return The file's location.
*/ */
public static FileLocation create(String fileFullPath) { public static FileLocation create(String fileFullPath) {
if (fileFullPath.startsWith("http://") || fileFullPath.startsWith("https://") || fileFullPath.startsWith("ftp://")) { if (fileFullPath.startsWith("http://") || fileFullPath.startsWith("https://")
|| fileFullPath.startsWith("ftp://")) {
try { try {
return new URLFileLocation(new URL(fileFullPath)); return new URLFileLocation(new URL(fileFullPath));
} catch (MalformedURLException mue) { } catch (MalformedURLException mue) {
@@ -39,23 +39,21 @@ public abstract class FileLocation {
} }
return new FileFileLocation(new File(fileFullPath)); return new FileFileLocation(new File(fileFullPath));
} }
/** /**
* Creates a {@link FileLocation} instance for the specified local file. * Creates a {@link FileLocation} instance for the specified local file.
* *
* @param file * @param file A local file.
* A local file.
* @return The file's location. * @return The file's location.
*/ */
public static FileLocation create(File file) { public static FileLocation create(File file) {
return new FileFileLocation(file); return new FileFileLocation(file);
} }
/** /**
* Creates a {@link FileLocation} instance for the specified file. * Creates a {@link FileLocation} instance for the specified file.
* *
* @param url * @param url The URL of a file.
* The URL of a file.
* @return The file's location. * @return The file's location.
*/ */
public static FileLocation create(URL url) { public static FileLocation create(URL url) {
@@ -64,25 +62,25 @@ public abstract class FileLocation {
} }
return new URLFileLocation(url); return new URLFileLocation(url);
} }
/** /**
* Returns the last time this file was modified, or * Returns the last time this file was modified, or
* {@link TextEditorPane#LAST_MODIFIED_UNKNOWN} if this value cannot be * {@link TextEditorPane#LAST_MODIFIED_UNKNOWN} if this value cannot be computed
* computed (such as for a remote file). * (such as for a remote file).
* *
* @return The last time this file was modified. * @return The last time this file was modified.
*/ */
protected abstract long getActualLastModified(); protected abstract long getActualLastModified();
/** /**
* Returns the full path to the file. This will be stripped of * Returns the full path to the file. This will be stripped of sensitive
* sensitive information such as passwords for remote files. * information such as passwords for remote files.
* *
* @return The full path to the file. * @return The full path to the file.
* @see #getFileName() * @see #getFileName()
*/ */
public abstract String getFileFullPath(); public abstract String getFileFullPath();
/** /**
* Returns the name of the file. * Returns the name of the file.
* *
@@ -90,26 +88,24 @@ public abstract class FileLocation {
* @see #getFileFullPath() * @see #getFileFullPath()
*/ */
public abstract String getFileName(); public abstract String getFileName();
/** /**
* Opens an input stream for reading from this file. * Opens an input stream for reading from this file.
* *
* @return The input stream. * @return The input stream.
* @throws IOException * @throws IOException If the file does not exist, or some other IO error
* If the file does not exist, or some other IO error * occurs.
* occurs.
*/ */
protected abstract InputStream getInputStream() throws IOException; protected abstract InputStream getInputStream() throws IOException;
/** /**
* Opens an output stream for writing this file. * Opens an output stream for writing this file.
* *
* @return An output stream. * @return An output stream.
* @throws IOException * @throws IOException If an IO error occurs.
* If an IO error occurs.
*/ */
protected abstract OutputStream getOutputStream() throws IOException; protected abstract OutputStream getOutputStream() throws IOException;
/** /**
* Returns whether this file location is a local file. * Returns whether this file location is a local file.
* *
@@ -117,16 +113,15 @@ public abstract class FileLocation {
* @see #isLocalAndExists() * @see #isLocalAndExists()
*/ */
public abstract boolean isLocal(); public abstract boolean isLocal();
/** /**
* Returns whether this file location is a local file that already * Returns whether this file location is a local file that already exists.
* exists.
* *
* @return Whether this file is local and actually exists. * @return Whether this file is local and actually exists.
* @see #isLocal() * @see #isLocal()
*/ */
public abstract boolean isLocalAndExists(); public abstract boolean isLocalAndExists();
/** /**
* Returns whether this file location is a remote location. * Returns whether this file location is a remote location.
* *
@@ -28,17 +28,16 @@ import org.fife.ui.rtextarea.IconRowHeader;
* @version 1.0 * @version 1.0
*/ */
public class FoldingAwareIconRowHeader extends IconRowHeader { public class FoldingAwareIconRowHeader extends IconRowHeader {
/** /**
* Constructor. * Constructor.
* *
* @param textArea * @param textArea The parent text area.
* The parent text area.
*/ */
public FoldingAwareIconRowHeader(RSyntaxTextArea textArea) { public FoldingAwareIconRowHeader(RSyntaxTextArea textArea) {
super(textArea); super(textArea);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -160,11 +159,11 @@ public class FoldingAwareIconRowHeader extends IconRowHeader {
} }
} }
} }
/** /**
* Paints icons when line wrapping is enabled. Note that this does not * Paints icons when line wrapping is enabled. Note that this does not override
* override the parent class's implementation to avoid this version being * the parent class's implementation to avoid this version being called when
* called when line wrapping is disabled. * line wrapping is disabled.
*/ */
private void paintComponentWrapped(Graphics g) { private void paintComponentWrapped(Graphics g) {
// The variables we use are as follows: // The variables we use are as follows:
@@ -20,49 +20,49 @@ import javax.swing.text.Element;
import org.fife.ui.rtextarea.SmartHighlightPainter; import org.fife.ui.rtextarea.SmartHighlightPainter;
/** /**
* Marks occurrences of the current token for HTML. Tags that require a * Marks occurrences of the current token for HTML. Tags that require a closing
* closing tag have their "opposite" tag closed. * tag have their "opposite" tag closed.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public class HtmlOccurrenceMarker implements OccurrenceMarker { public class HtmlOccurrenceMarker implements OccurrenceMarker {
private static final char[] CLOSE_TAG_START = { '<', '/' }; private static final char[] CLOSE_TAG_START = { '<', '/' };
private static final char[] TAG_SELF_CLOSE = { '/', '>' }; private static final char[] TAG_SELF_CLOSE = { '/', '>' };
private static final Set<String> TAGS_REQUIRING_CLOSING = getRequiredClosingTags(); private static final Set<String> TAGS_REQUIRING_CLOSING = getRequiredClosingTags();
public static final Set<String> getRequiredClosingTags() { public static final Set<String> getRequiredClosingTags() {
final String[] tags = { "html", "head", "title", "style", "script", "noscript", "body", "section", "nav", "article", "aside", "h1", final String[] tags = { "html", "head", "title", "style", "script", "noscript", "body", "section", "nav",
"h2", "h3", "h4", "h5", "h6", "header", "footer", "address", "pre", "dialog", "blockquote", "ol", "ul", "dl", "a", "q", "article", "aside", "h1", "h2", "h3", "h4", "h5", "h6", "header", "footer", "address", "pre", "dialog",
"cite", "em", "strong", "small", "mark", "dfn", "abbr", "time", "progress", "meter", "code", "var", "samp", "kbd", "sub", "blockquote", "ol", "ul", "dl", "a", "q", "cite", "em", "strong", "small", "mark", "dfn", "abbr",
"sup", "span", "i", "b", "bdo", "ruby", "rt", "rp", "ins", "del", "figure", "iframe", "object", "video", "audio", "canvas", "time", "progress", "meter", "code", "var", "samp", "kbd", "sub", "sup", "span", "i", "b", "bdo",
"map", "table", "caption", "form", "fieldset", "label", "button", "select", "datalist", "textarea", "output", "details", "ruby", "rt", "rp", "ins", "del", "figure", "iframe", "object", "video", "audio", "canvas", "map",
"bb", "menu", "legend", "div", "table", "caption", "form", "fieldset", "label", "button", "select", "datalist", "textarea", "output",
"details", "bb", "menu", "legend", "div",
// Obsolete elements // Obsolete elements
"acronym", "applet", "big", "blink", "center", "dir", "font", "frame", "frameset", "isindex", "listing", "marquee", "nobr", "acronym", "applet", "big", "blink", "center", "dir", "font", "frame", "frameset", "isindex", "listing",
"noembed", "noframes", "plaintext", "s", "spacer", "strike", "tt", "u", "xmp", }; "marquee", "nobr", "noembed", "noframes", "plaintext", "s", "spacer", "strike", "tt", "u", "xmp", };
return new HashSet<String>(Arrays.asList(tags)); return new HashSet<String>(Arrays.asList(tags));
} }
/** /**
* If the caret is inside of a tag, this method returns the token * If the caret is inside of a tag, this method returns the token representing
* representing the tag name; otherwise, <code>null</code> is returned. * the tag name; otherwise, <code>null</code> is returned.
* <p> * <p>
* *
* Currently, this method only checks for tag names on the same line as * Currently, this method only checks for tag names on the same line as the
* the caret, for simplicity. In the future it could check prior lines * caret, for simplicity. In the future it could check prior lines until the tag
* until the tag name is found. * name is found.
* *
* @param textArea * @param textArea The text area.
* The text area. * @param occurrenceMarker The occurrence marker.
* @param occurrenceMarker * @return The token to mark occurrences of. Note that, if the specified
* The occurrence marker. * occurrence marker identifies tokens other than tag names, these other
* @return The token to mark occurrences of. Note that, if the * element types may be returned.
* specified occurrence marker identifies tokens other than
* tag names, these other element types may be returned.
*/ */
public static final Token getTagNameTokenForCaretOffset(RSyntaxTextArea textArea, OccurrenceMarker occurrenceMarker) { public static final Token getTagNameTokenForCaretOffset(RSyntaxTextArea textArea,
OccurrenceMarker occurrenceMarker) {
// Get the tag name token. // Get the tag name token.
// For now, we only check for tags on the current line, for simplicity. // For now, we only check for tags on the current line, for simplicity.
int dot = textArea.getCaretPosition(); int dot = textArea.getCaretPosition();
@@ -93,7 +93,7 @@ public class HtmlOccurrenceMarker implements OccurrenceMarker {
} }
return toMark; return toMark;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -101,7 +101,7 @@ public class HtmlOccurrenceMarker implements OccurrenceMarker {
public Token getTokenToMark(RSyntaxTextArea textArea) { public Token getTokenToMark(RSyntaxTextArea textArea) {
return getTagNameTokenForCaretOffset(textArea, this); return getTagNameTokenForCaretOffset(textArea, this);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -109,7 +109,7 @@ public class HtmlOccurrenceMarker implements OccurrenceMarker {
public boolean isValidType(RSyntaxTextArea textArea, Token t) { public boolean isValidType(RSyntaxTextArea textArea, Token t) {
return textArea.getMarkOccurrencesOfTokenType(t.getType()); return textArea.getMarkOccurrencesOfTokenType(t.getType());
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -254,15 +254,15 @@ public class HtmlOccurrenceMarker implements OccurrenceMarker {
} while (curLine >= 0); } while (curLine >= 0);
} }
} }
/** /**
* Used internally when searching backward for a matching "open" tag. * Used internally when searching backward for a matching "open" tag.
*/ */
private static class Entry { private static class Entry {
private boolean open; private boolean open;
private Token t; private Token t;
Entry(boolean open, Token t) { Entry(boolean open, Token t) {
this.open = open; this.open = open;
this.t = t; this.t = t;
@@ -28,17 +28,14 @@ package org.fife.ui.rsyntaxtextarea;
* @version 1.0 * @version 1.0
*/ */
public interface LinkGenerator { public interface LinkGenerator {
/** /**
* If a region of text under the mouse position should be considered a * If a region of text under the mouse position should be considered a
* hyperlink, a result object is returned. This object describes what * hyperlink, a result object is returned. This object describes what region of
* region of text is the link, and what action to perform if the link is * text is the link, and what action to perform if the link is clicked.
* clicked.
* *
* @param textArea * @param textArea The text component.
* The text component. * @param offs The offset in the document under the mouse position.
* @param offs
* The offset in the document under the mouse position.
* @return The link information, or <code>null</code> if no link is at the * @return The link information, or <code>null</code> if no link is at the
* specified offset. * specified offset.
*/ */
@@ -23,19 +23,19 @@ import javax.swing.event.HyperlinkEvent;
* @see SelectRegionLinkGeneratorResult * @see SelectRegionLinkGeneratorResult
*/ */
public interface LinkGeneratorResult { public interface LinkGeneratorResult {
/** /**
* Executes the action associated with this object. If the result is a * Executes the action associated with this object. If the result is a URL to
* URL to open, a standard hyperlink event can be returned. Alternatively, * open, a standard hyperlink event can be returned. Alternatively,
* <code>null</code> can be returned and the action performed in this * <code>null</code> can be returned and the action performed in this method
* method itself. * itself.
* *
* @return The hyperlink event to broadcast from the text area, or * @return The hyperlink event to broadcast from the text area, or
* <code>null</code> if the action's behavior occurs in this method * <code>null</code> if the action's behavior occurs in this method
* directly. * directly.
*/ */
HyperlinkEvent execute(); HyperlinkEvent execute();
/** /**
* Returns the starting offset of the link specified by the parent * Returns the starting offset of the link specified by the parent
* <code>LinkGenerator</code>. * <code>LinkGenerator</code>.
@@ -19,15 +19,15 @@ import javax.swing.text.Caret;
import org.fife.ui.rtextarea.SmartHighlightPainter; import org.fife.ui.rtextarea.SmartHighlightPainter;
/** /**
* Marks all occurrences of the token at the current caret position, if it is * Marks all occurrences of the token at the current caret position, if it is an
* an identifier. * identifier.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
* @see OccurrenceMarker * @see OccurrenceMarker
*/ */
class MarkOccurrencesSupport implements CaretListener, ActionListener { class MarkOccurrencesSupport implements CaretListener, ActionListener {
private RSyntaxTextArea textArea; private RSyntaxTextArea textArea;
private Timer timer; private Timer timer;
private SmartHighlightPainter p; private SmartHighlightPainter p;
@@ -39,36 +39,33 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
* The default delay. * The default delay.
*/ */
static final int DEFAULT_DELAY_MS = 1000; static final int DEFAULT_DELAY_MS = 1000;
/** /**
* Constructor. Creates a listener with a 1 second delay. * Constructor. Creates a listener with a 1 second delay.
*/ */
MarkOccurrencesSupport() { MarkOccurrencesSupport() {
this(DEFAULT_DELAY_MS); this(DEFAULT_DELAY_MS);
} }
/** /**
* Constructor. * Constructor.
* *
* @param delay * @param delay The delay between when the caret last moves and when the text
* The delay between when the caret last moves and when the * should be scanned for matching occurrences. This should be in
* text should be scanned for matching occurrences. This should * milliseconds.
* be in milliseconds.
*/ */
MarkOccurrencesSupport(int delay) { MarkOccurrencesSupport(int delay) {
this(delay, DEFAULT_COLOR); this(delay, DEFAULT_COLOR);
} }
/** /**
* Constructor. * Constructor.
* *
* @param delay * @param delay The delay between when the caret last moves and when the text
* The delay between when the caret last moves and when the * should be scanned for matching occurrences. This should be in
* text should be scanned for matching occurrences. This should * milliseconds.
* be in milliseconds. * @param color The color to use to mark the occurrences. This cannot be
* @param color * <code>null</code>.
* The color to use to mark the occurrences. This cannot be
* <code>null</code>.
*/ */
MarkOccurrencesSupport(int delay, Color color) { MarkOccurrencesSupport(int delay, Color color) {
timer = new Timer(delay, this); timer = new Timer(delay, this);
@@ -76,18 +73,17 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
p = new SmartHighlightPainter(); p = new SmartHighlightPainter();
setColor(color); setColor(color);
} }
/** /**
* Called after the caret has been moved and a fixed time delay has * Called after the caret has been moved and a fixed time delay has elapsed.
* elapsed. This locates and highlights all occurrences of the identifier * This locates and highlights all occurrences of the identifier at the caret
* at the caret position, if any. * position, if any.
* <p> * <p>
* *
* Callers should not call this method directly, but should rather prefer * Callers should not call this method directly, but should rather prefer
* {@link #doMarkOccurrences()} to mark occurrences. * {@link #doMarkOccurrences()} to mark occurrences.
* *
* @param e * @param e The event.
* The event.
* @see #doMarkOccurrences() * @see #doMarkOccurrences()
*/ */
@Override @Override
@@ -124,18 +120,17 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
textArea.fireMarkedOccurrencesChanged(); textArea.fireMarkedOccurrencesChanged();
} }
} }
/** /**
* Called when the caret moves in the text area. * Called when the caret moves in the text area.
* *
* @param e * @param e The event.
* The event.
*/ */
@Override @Override
public void caretUpdate(CaretEvent e) { public void caretUpdate(CaretEvent e) {
timer.restart(); timer.restart();
} }
/** /**
* Removes all highlights added to the text area by this listener. * Removes all highlights added to the text area by this listener.
*/ */
@@ -145,16 +140,15 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
h.clearMarkOccurrencesHighlights(); h.clearMarkOccurrencesHighlights();
} }
} }
/** /**
* Immediately marks all occurrences of the token at the current caret * Immediately marks all occurrences of the token at the current caret position.
* position.
*/ */
public void doMarkOccurrences() { public void doMarkOccurrences() {
timer.stop(); timer.stop();
actionPerformed(null); actionPerformed(null);
} }
/** /**
* Returns the color being used to mark occurrences. * Returns the color being used to mark occurrences.
* *
@@ -164,7 +158,7 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
public Color getColor() { public Color getColor() {
return (Color) p.getPaint(); return (Color) p.getPaint();
} }
/** /**
* Returns the delay, in milliseconds. * Returns the delay, in milliseconds.
* *
@@ -174,7 +168,7 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
public int getDelay() { public int getDelay() {
return timer.getDelay(); return timer.getDelay();
} }
/** /**
* Returns whether a border is painted around marked occurrences. * Returns whether a border is painted around marked occurrences.
* *
@@ -185,13 +179,12 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
public boolean getPaintBorder() { public boolean getPaintBorder() {
return p.getPaintBorder(); return p.getPaintBorder();
} }
/** /**
* Installs this listener on a text area. If it is already installed on * Installs this listener on a text area. If it is already installed on another
* another text area, it is uninstalled first. * text area, it is uninstalled first.
* *
* @param textArea * @param textArea The text area to install on.
* The text area to install on.
*/ */
public void install(RSyntaxTextArea textArea) { public void install(RSyntaxTextArea textArea) {
if (this.textArea != null) { if (this.textArea != null) {
@@ -203,12 +196,11 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
setColor(textArea.getMarkOccurrencesColor()); setColor(textArea.getMarkOccurrencesColor());
} }
} }
/** /**
* Sets the color to use when marking occurrences. * Sets the color to use when marking occurrences.
* *
* @param color * @param color The color to use.
* The color to use.
* @see #getColor() * @see #getColor()
* @see #setPaintBorder(boolean) * @see #setPaintBorder(boolean)
*/ */
@@ -219,25 +211,23 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
caretUpdate(null); // Force a highlight repaint. caretUpdate(null); // Force a highlight repaint.
} }
} }
/** /**
* Sets the delay between the last caret position change and when the * Sets the delay between the last caret position change and when the text is
* text is scanned for matching identifiers. A delay is needed to prevent * scanned for matching identifiers. A delay is needed to prevent repeated
* repeated scanning while the user is typing. * scanning while the user is typing.
* *
* @param delay * @param delay The new delay.
* The new delay.
* @see #getDelay() * @see #getDelay()
*/ */
public void setDelay(int delay) { public void setDelay(int delay) {
timer.setInitialDelay(delay); timer.setInitialDelay(delay);
} }
/** /**
* Toggles whether a border is painted around marked highlights. * Toggles whether a border is painted around marked highlights.
* *
* @param paint * @param paint Whether to paint a border.
* Whether to paint a border.
* @see #getPaintBorder() * @see #getPaintBorder()
* @see #setColor(Color) * @see #setColor(Color)
*/ */
@@ -249,10 +239,10 @@ class MarkOccurrencesSupport implements CaretListener, ActionListener {
} }
} }
} }
/** /**
* Uninstalls this listener from the current text area. Does nothing if * Uninstalls this listener from the current text area. Does nothing if it not
* it not currently installed on any text area. * currently installed on any text area.
* *
* @see #install(RSyntaxTextArea) * @see #install(RSyntaxTextArea)
*/ */
@@ -41,11 +41,11 @@ import org.fife.ui.rsyntaxtextarea.focusabletip.TipUtil;
* @version 1.0 * @version 1.0
*/ */
class MatchedBracketPopup extends JWindow { class MatchedBracketPopup extends JWindow {
private RSyntaxTextArea textArea; private RSyntaxTextArea textArea;
private transient Listener listener; private transient Listener listener;
private static final int LEFT_EMPTY_BORDER = 5; private static final int LEFT_EMPTY_BORDER = 5;
MatchedBracketPopup(Window parent, RSyntaxTextArea textArea, int offsToRender) { MatchedBracketPopup(Window parent, RSyntaxTextArea textArea, int offsToRender) {
super(parent); super(parent);
this.textArea = textArea; this.textArea = textArea;
@@ -59,7 +59,7 @@ class MatchedBracketPopup extends JWindow {
listener = new Listener(); listener = new Listener();
setLocation(); setLocation();
} }
/** /**
* Overridden to ensure this popup stays in a specific size range. * Overridden to ensure this popup stays in a specific size range.
*/ */
@@ -71,7 +71,7 @@ class MatchedBracketPopup extends JWindow {
} }
return size; return size;
} }
private String getText(int offsToRender) { private String getText(int offsToRender) {
int line = 0; int line = 0;
try { try {
@@ -110,7 +110,7 @@ class MatchedBracketPopup extends JWindow {
} }
return sb.toString(); return sb.toString();
} }
/** /**
* Adds key bindings to this popup. * Adds key bindings to this popup.
*/ */
@@ -121,10 +121,9 @@ class MatchedBracketPopup extends JWindow {
im.put(escapeKS, "onEscape"); im.put(escapeKS, "onEscape");
am.put("onEscape", new EscapeAction()); am.put("onEscape", new EscapeAction());
} }
/** /**
* Positions this popup to be in the top right-hand corner of the parent * Positions this popup to be in the top right-hand corner of the parent editor.
* editor.
*/ */
private void setLocation() { private void setLocation() {
Point topLeft = textArea.getVisibleRect().getLocation(); Point topLeft = textArea.getVisibleRect().getLocation();
@@ -132,23 +131,23 @@ class MatchedBracketPopup extends JWindow {
topLeft.y = Math.max(topLeft.y - 24, 0); topLeft.y = Math.max(topLeft.y - 24, 0);
setLocation(topLeft.x - LEFT_EMPTY_BORDER, topLeft.y); setLocation(topLeft.x - LEFT_EMPTY_BORDER, topLeft.y);
} }
/** /**
* Action performed when Escape is pressed in this popup. * Action performed when Escape is pressed in this popup.
*/ */
private class EscapeAction extends AbstractAction { private class EscapeAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
listener.uninstallAndHide(); listener.uninstallAndHide();
} }
} }
/** /**
* Listens for events in this popup. * Listens for events in this popup.
*/ */
private class Listener extends WindowAdapter implements ComponentListener { private class Listener extends WindowAdapter implements ComponentListener {
Listener() { Listener() {
addWindowFocusListener(this); addWindowFocusListener(this);
// If anything happens to the "parent" window, hide this popup // If anything happens to the "parent" window, hide this popup
@@ -157,42 +156,42 @@ class MatchedBracketPopup extends JWindow {
parent.addWindowListener(this); parent.addWindowListener(this);
parent.addComponentListener(this); parent.addComponentListener(this);
} }
@Override @Override
public void componentResized(ComponentEvent e) { public void componentResized(ComponentEvent e) {
uninstallAndHide(); uninstallAndHide();
} }
@Override @Override
public void componentMoved(ComponentEvent e) { public void componentMoved(ComponentEvent e) {
uninstallAndHide(); uninstallAndHide();
} }
@Override @Override
public void componentShown(ComponentEvent e) { public void componentShown(ComponentEvent e) {
uninstallAndHide(); uninstallAndHide();
} }
@Override @Override
public void componentHidden(ComponentEvent e) { public void componentHidden(ComponentEvent e) {
uninstallAndHide(); uninstallAndHide();
} }
@Override @Override
public void windowActivated(WindowEvent e) { public void windowActivated(WindowEvent e) {
checkForParentWindowEvent(e); checkForParentWindowEvent(e);
} }
@Override @Override
public void windowLostFocus(WindowEvent e) { public void windowLostFocus(WindowEvent e) {
uninstallAndHide(); uninstallAndHide();
} }
@Override @Override
public void windowIconified(WindowEvent e) { public void windowIconified(WindowEvent e) {
checkForParentWindowEvent(e); checkForParentWindowEvent(e);
} }
private boolean checkForParentWindowEvent(WindowEvent e) { private boolean checkForParentWindowEvent(WindowEvent e) {
if (e.getSource() == getParent()) { if (e.getSource() == getParent()) {
uninstallAndHide(); uninstallAndHide();
@@ -200,7 +199,7 @@ class MatchedBracketPopup extends JWindow {
} }
return false; return false;
} }
private void uninstallAndHide() { private void uninstallAndHide() {
Window parent = (Window) getParent(); Window parent = (Window) getParent();
parent.removeWindowFocusListener(this); parent.removeWindowFocusListener(this);
@@ -10,52 +10,44 @@ import org.fife.ui.rtextarea.SmartHighlightPainter;
/** /**
* An <code>OccurrenceMarker</code> is called when the caret stops moving after * An <code>OccurrenceMarker</code> is called when the caret stops moving after
* a short period. If the current {@link TokenMaker} returns an instance of * a short period. If the current {@link TokenMaker} returns an instance of this
* this class, it is told to mark all occurrences of the identifier at the * class, it is told to mark all occurrences of the identifier at the caret
* caret position. * position.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public interface OccurrenceMarker { public interface OccurrenceMarker {
/** /**
* Returns the token to mark occurrences, of, provided it matches the * Returns the token to mark occurrences, of, provided it matches the criteria
* criteria put forth by {@link #isValidType(RSyntaxTextArea, Token)}. * put forth by {@link #isValidType(RSyntaxTextArea, Token)}. For most
* For most languages, this method should return the token at the caret * languages, this method should return the token at the caret position.
* position.
* *
* @param textArea * @param textArea The text area.
* The text area. * @return The token to (possibly) mark occurrences of, or <code>null</code> if
* @return The token to (possibly) mark occurrences of, or * none.
* <code>null</code> if none.
*/ */
Token getTokenToMark(RSyntaxTextArea textArea); Token getTokenToMark(RSyntaxTextArea textArea);
/** /**
* Returns whether the specified token is a type that we can do a * Returns whether the specified token is a type that we can do a "mark
* "mark occurrences" of. Typically, this will delegate to * occurrences" of. Typically, this will delegate to
* {@link RSyntaxTextArea#getMarkOccurrencesOfTokenType(int)}. * {@link RSyntaxTextArea#getMarkOccurrencesOfTokenType(int)}.
* *
* @param textArea * @param textArea The text area.
* The text area. * @param t The token.
* @param t
* The token.
* @return Whether we should mark all occurrences of this token. * @return Whether we should mark all occurrences of this token.
*/ */
boolean isValidType(RSyntaxTextArea textArea, Token t); boolean isValidType(RSyntaxTextArea textArea, Token t);
/** /**
* Called when occurrences of a token should be marked. * Called when occurrences of a token should be marked.
* *
* @param doc * @param doc The document.
* The document. * @param t The document whose relevant occurrences should be marked.
* @param t * @param h The highlighter to add the highlights to.
* The document whose relevant occurrences should be marked. * @param p The painter for the highlights.
* @param h
* The highlighter to add the highlights to.
* @param p
* The painter for the highlights.
*/ */
void markOccurrences(RSyntaxDocument doc, Token t, RSyntaxTextAreaHighlighter h, SmartHighlightPainter p); void markOccurrences(RSyntaxDocument doc, Token t, RSyntaxTextAreaHighlighter h, SmartHighlightPainter p);
} }
+116 -153
View File
@@ -46,7 +46,7 @@ import org.fife.ui.rtextarea.RTextAreaHighlighter.HighlightInfo;
* @version 0.9 * @version 0.9
*/ */
class ParserManager implements DocumentListener, ActionListener, HyperlinkListener, PropertyChangeListener { class ParserManager implements DocumentListener, ActionListener, HyperlinkListener, PropertyChangeListener {
private RSyntaxTextArea textArea; private RSyntaxTextArea textArea;
private List<Parser> parsers; private List<Parser> parsers;
private Timer timer; private Timer timer;
@@ -55,20 +55,21 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
private Position firstOffsetModded; private Position firstOffsetModded;
private Position lastOffsetModded; private Position lastOffsetModded;
/** /**
* Mapping of notices to their highlights in the editor. Can't use a Map * Mapping of notices to their highlights in the editor. Can't use a Map since
* since parsers could return two <code>ParserNotice</code>s that compare * parsers could return two <code>ParserNotice</code>s that compare equally via
* equally via <code>equals()</code>. Real-world example: The Perl * <code>equals()</code>. Real-world example: The Perl compiler will return 2+
* compiler will return 2+ identical error messages if the same error is * identical error messages if the same error is committed in a single line more
* committed in a single line more than once. * than once.
*/ */
private List<NoticeHighlightPair> noticeHighlightPairs; private List<NoticeHighlightPair> noticeHighlightPairs;
/** /**
* Painter used to underline errors. * Painter used to underline errors.
*/ */
private SquiggleUnderlineHighlightPainter parserErrorHighlightPainter = new SquiggleUnderlineHighlightPainter(Color.RED); private SquiggleUnderlineHighlightPainter parserErrorHighlightPainter = new SquiggleUnderlineHighlightPainter(
Color.RED);
/** /**
* If this system property is set to <code>true</code>, debug messages * If this system property is set to <code>true</code>, debug messages will be
* will be printed to stdout to help diagnose parsing issues. * printed to stdout to help diagnose parsing issues.
*/ */
private static final String PROPERTY_DEBUG_PARSING = "rsta.debugParsing"; private static final String PROPERTY_DEBUG_PARSING = "rsta.debugParsing";
/** /**
@@ -76,31 +77,26 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
*/ */
private static final boolean DEBUG_PARSING; private static final boolean DEBUG_PARSING;
/** /**
* The default delay between the last key press and when the document * The default delay between the last key press and when the document is parsed,
* is parsed, in milliseconds. * in milliseconds.
*/ */
private static final int DEFAULT_DELAY_MS = 1250; private static final int DEFAULT_DELAY_MS = 1250;
/** /**
* Constructor. * Constructor.
* *
* @param textArea * @param textArea The text area whose document the parser will be parsing.
* The text area whose document the parser will be
* parsing.
*/ */
ParserManager(RSyntaxTextArea textArea) { ParserManager(RSyntaxTextArea textArea) {
this(DEFAULT_DELAY_MS, textArea); this(DEFAULT_DELAY_MS, textArea);
} }
/** /**
* Constructor. * Constructor.
* *
* @param delay * @param delay The delay between the last key press and when the document is
* The delay between the last key press and when the document * parsed.
* is parsed. * @param textArea The text area whose document the parser will be parsing.
* @param textArea
* The text area whose document the parser will be
* parsing.
*/ */
ParserManager(int delay, RSyntaxTextArea textArea) { ParserManager(int delay, RSyntaxTextArea textArea) {
this.textArea = textArea; this.textArea = textArea;
@@ -111,12 +107,11 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
timer.setRepeats(false); timer.setRepeats(false);
running = true; running = true;
} }
/** /**
* Called when the timer fires (e.g. it's time to parse the document). * Called when the timer fires (e.g. it's time to parse the document).
* *
* @param e * @param e The event.
* The event.
*/ */
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@@ -132,7 +127,8 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument();
Element root = doc.getDefaultRootElement(); Element root = doc.getDefaultRootElement();
int firstLine = firstOffsetModded == null ? 0 : root.getElementIndex(firstOffsetModded.getOffset()); int firstLine = firstOffsetModded == null ? 0 : root.getElementIndex(firstOffsetModded.getOffset());
int lastLine = lastOffsetModded == null ? root.getElementCount() - 1 : root.getElementIndex(lastOffsetModded.getOffset()); int lastLine = lastOffsetModded == null ? root.getElementCount() - 1
: root.getElementIndex(lastOffsetModded.getOffset());
firstOffsetModded = lastOffsetModded = null; firstOffsetModded = lastOffsetModded = null;
if (DEBUG_PARSING) { if (DEBUG_PARSING) {
System.out.println("[DEBUG]: Minimum lines to parse: " + firstLine + "-" + lastLine); System.out.println("[DEBUG]: Minimum lines to parse: " + firstLine + "-" + lastLine);
@@ -158,13 +154,11 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
System.out.println("Total parsing time: " + time + " seconds"); System.out.println("Total parsing time: " + time + " seconds");
} }
} }
/** /**
* Adds a parser for the text area. * Adds a parser for the text area.
* *
* @param parser * @param parser The new parser. If this is <code>null</code>, nothing happens.
* The new parser. If this is <code>null</code>, nothing
* happens.
* @see #getParser(int) * @see #getParser(int)
* @see #removeParser(Parser) * @see #removeParser(Parser)
*/ */
@@ -183,13 +177,12 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
} }
} }
} }
/** /**
* Adds highlights for a list of parser notices. Any current notices * Adds highlights for a list of parser notices. Any current notices from the
* from the same Parser, in the same parsed range, are removed. * same Parser, in the same parsed range, are removed.
* *
* @param res * @param res The result of a parsing.
* The result of a parsing.
* @see #clearParserNoticeHighlights() * @see #clearParserNoticeHighlights()
*/ */
private void addParserNoticeHighlights(ParseResult res) { private void addParserNoticeHighlights(ParseResult res) {
@@ -227,16 +220,16 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
System.out.println("[DEBUG]: Done adding parser notices from " + res.getParser()); System.out.println("[DEBUG]: Done adding parser notices from " + res.getParser());
} }
} }
/** /**
* Called when the document is modified. * Called when the document is modified.
* *
* @param e * @param e The document event.
* The document event.
*/ */
@Override @Override
public void changedUpdate(DocumentEvent e) {} public void changedUpdate(DocumentEvent e) {
}
private void clearParserNoticeHighlights() { private void clearParserNoticeHighlights() {
RSyntaxTextAreaHighlighter h = (RSyntaxTextAreaHighlighter) textArea.getHighlighter(); RSyntaxTextAreaHighlighter h = (RSyntaxTextAreaHighlighter) textArea.getHighlighter();
if (h != null) { if (h != null) {
@@ -246,12 +239,11 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
noticeHighlightPairs.clear(); noticeHighlightPairs.clear();
} }
} }
/** /**
* Removes all parser notice highlights for a specific parser. * Removes all parser notice highlights for a specific parser.
* *
* @param parser * @param parser The parser whose highlights to remove.
* The parser whose highlights to remove.
*/ */
private void clearParserNoticeHighlights(Parser parser) { private void clearParserNoticeHighlights(Parser parser) {
RSyntaxTextAreaHighlighter h = (RSyntaxTextAreaHighlighter) textArea.getHighlighter(); RSyntaxTextAreaHighlighter h = (RSyntaxTextAreaHighlighter) textArea.getHighlighter();
@@ -268,7 +260,7 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
} }
} }
} }
/** /**
* Removes all parsers and any highlights they have created. * Removes all parsers and any highlights they have created.
* *
@@ -280,20 +272,18 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
parsers.clear(); parsers.clear();
textArea.fireParserNoticesChange(); textArea.fireParserNoticesChange();
} }
/** /**
* Forces the given {@link Parser} to re-parse the content of this text * Forces the given {@link Parser} to re-parse the content of this text area.
* area.
* <p> * <p>
* *
* This method can be useful when a <code>Parser</code> can be configured * This method can be useful when a <code>Parser</code> can be configured as to
* as to what notices it returns. For example, if a Java language parser * what notices it returns. For example, if a Java language parser can be
* can be configured to set whether no serialVersionUID is a warning, * configured to set whether no serialVersionUID is a warning, error, or
* error, or ignored, this method can be called after changing the expected * ignored, this method can be called after changing the expected notice type to
* notice type to have the document re-parsed. * have the document re-parsed.
* *
* @param parser * @param parser The index of the <code>Parser</code> to re-run.
* The index of the <code>Parser</code> to re-run.
* @see #getParser(int) * @see #getParser(int)
*/ */
public void forceReparsing(int parser) { public void forceReparsing(int parser) {
@@ -313,10 +303,10 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
doc.readUnlock(); doc.readUnlock();
} }
} }
/** /**
* Returns the delay between the last "concurrent" edit and when the * Returns the delay between the last "concurrent" edit and when the document is
* document is re-parsed. * re-parsed.
* *
* @return The delay, in milliseconds. * @return The delay, in milliseconds.
* @see #setDelay(int) * @see #setDelay(int)
@@ -324,12 +314,11 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
public int getDelay() { public int getDelay() {
return timer.getDelay(); return timer.getDelay();
} }
/** /**
* Returns the specified parser. * Returns the specified parser.
* *
* @param index * @param index The index of the parser.
* The index of the parser.
* @return The parser. * @return The parser.
* @see #getParserCount() * @see #getParserCount()
* @see #addParser(Parser) * @see #addParser(Parser)
@@ -338,7 +327,7 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
public Parser getParser(int index) { public Parser getParser(int index) {
return parsers.get(index); return parsers.get(index);
} }
/** /**
* Returns the number of registered parsers. * Returns the number of registered parsers.
* *
@@ -347,14 +336,12 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
public int getParserCount() { public int getParserCount() {
return parsers.size(); return parsers.size();
} }
/** /**
* Returns a list of the current parser notices for this text area. * Returns a list of the current parser notices for this text area. This method
* This method (like most Swing methods) should only be called on the * (like most Swing methods) should only be called on the EDT.
* EDT.
* *
* @return The list of notices. This will be an empty list if there are * @return The list of notices. This will be an empty list if there are none.
* none.
*/ */
public List<ParserNotice> getParserNotices() { public List<ParserNotice> getParserNotices() {
List<ParserNotice> notices = new ArrayList<ParserNotice>(); List<ParserNotice> notices = new ArrayList<ParserNotice>();
@@ -365,15 +352,13 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
} }
return notices; return notices;
} }
/** /**
* Returns the tool tip to display for a mouse event at the given * Returns the tool tip to display for a mouse event at the given location. This
* location. This method is overridden to give a registered parser a * method is overridden to give a registered parser a chance to display a tool
* chance to display a tool tip (such as an error description when the * tip (such as an error description when the mouse is over an error highlight).
* mouse is over an error highlight).
* *
* @param e * @param e The mouse event.
* The mouse event.
* @return The tool tip to display, and possibly a hyperlink event handler. * @return The tool tip to display, and possibly a hyperlink event handler.
*/ */
public ToolTipInfo getToolTipText(MouseEvent e) { public ToolTipInfo getToolTipText(MouseEvent e) {
@@ -385,19 +370,12 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
int pos = textArea.viewToModel(p); int pos = textArea.viewToModel(p);
/* /*
* Highlighter.Highlight[] highlights = textArea.getHighlighter(). * Highlighter.Highlight[] highlights = textArea.getHighlighter().
* getHighlights(); * getHighlights(); for (int i=0; i<highlights.length; i++) {
* for (int i=0; i<highlights.length; i++) { * Highlighter.Highlight h = highlights[i]; //if (h instanceof
* Highlighter.Highlight h = highlights[i]; * ParserNoticeHighlight) { // ParserNoticeHighlight pnh =
* //if (h instanceof ParserNoticeHighlight) { * (ParserNoticeHighlight)h; int start = h.getStartOffset(); int end =
* // ParserNoticeHighlight pnh = (ParserNoticeHighlight)h; * h.getEndOffset(); if (start<=pos && end>=pos) { //return pnh.getMessage();
* int start = h.getStartOffset(); * return textArea.getText(start, end-start); } //} }
* int end = h.getEndOffset();
* if (start<=pos && end>=pos) {
* //return pnh.getMessage();
* return textArea.getText(start, end-start);
* }
* //}
* }
*/ */
if (noticeHighlightPairs != null) { if (noticeHighlightPairs != null) {
for (NoticeHighlightPair pair : noticeHighlightPairs) { for (NoticeHighlightPair pair : noticeHighlightPairs) {
@@ -418,25 +396,23 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
URL imageBase = parserForTip == null ? null : parserForTip.getImageBase(); URL imageBase = parserForTip == null ? null : parserForTip.getImageBase();
return new ToolTipInfo(tip, listener, imageBase); return new ToolTipInfo(tip, listener, imageBase);
} }
/** /**
* Called when the document is modified. * Called when the document is modified.
* *
* @param e * @param e The document event.
* The document event.
*/ */
public void handleDocumentEvent(DocumentEvent e) { public void handleDocumentEvent(DocumentEvent e) {
if (running && parsers.size() > 0) { if (running && parsers.size() > 0) {
timer.restart(); timer.restart();
} }
} }
/** /**
* Called when the user clicks a hyperlink in a * Called when the user clicks a hyperlink in a
* {@link org.fife.ui.rsyntaxtextarea.focusabletip.FocusableTip}. * {@link org.fife.ui.rsyntaxtextarea.focusabletip.FocusableTip}.
* *
* @param e * @param e The event.
* The event.
*/ */
@Override @Override
public void hyperlinkUpdate(HyperlinkEvent e) { public void hyperlinkUpdate(HyperlinkEvent e) {
@@ -444,12 +420,11 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
parserForTip.getHyperlinkListener().linkClicked(textArea, e); parserForTip.getHyperlinkListener().linkClicked(textArea, e);
} }
} }
/** /**
* Called when the document is modified. * Called when the document is modified.
* *
* @param e * @param e The document event.
* The document event.
*/ */
@Override @Override
public void insertUpdate(DocumentEvent e) { public void insertUpdate(DocumentEvent e) {
@@ -469,14 +444,12 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
} }
handleDocumentEvent(e); handleDocumentEvent(e);
} }
/** /**
* Returns whether a parser notice contains the specified offset. * Returns whether a parser notice contains the specified offset.
* *
* @param notice * @param notice The notice.
* The notice. * @param offs The offset.
* @param offs
* The offset.
* @return Whether the notice contains the offset. * @return Whether the notice contains the offset.
*/ */
private boolean noticeContainsPosition(ParserNotice notice, int offs) { private boolean noticeContainsPosition(ParserNotice notice, int offs) {
@@ -492,20 +465,18 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
Element elem = root.getElement(line); Element elem = root.getElement(line);
return elem != null && offs >= elem.getStartOffset() && offs < elem.getEndOffset(); return elem != null && offs >= elem.getStartOffset() && offs < elem.getEndOffset();
} }
/** /**
* Since <code>viewToModel()</code> returns the <em>closest</em> model * Since <code>viewToModel()</code> returns the <em>closest</em> model position,
* position, and the position doesn't <em>necessarily</em> contain the * and the position doesn't <em>necessarily</em> contain the point passed in as
* point passed in as an argument, this method checks whether the point is * an argument, this method checks whether the point is indeed contained in the
* indeed contained in the view rectangle for the specified offset. * view rectangle for the specified offset.
* *
* @param notice * @param notice The parser notice.
* The parser notice. * @param p The point possibly contained in the view range of the parser
* @param p * notice.
* The point possibly contained in the view range of the * @return Whether the parser notice actually contains the specified point in
* parser notice. * the view.
* @return Whether the parser notice actually contains the specified point
* in the view.
*/ */
private boolean noticeContainsPointInView(ParserNotice notice, Point p) { private boolean noticeContainsPointInView(ParserNotice notice, Point p) {
try { try {
@@ -543,12 +514,11 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
return true; return true;
} }
} }
/** /**
* Called when a property we're interested in changes. * Called when a property we're interested in changes.
* *
* @param e * @param e The property change event.
* The property change event.
*/ */
@Override @Override
public void propertyChange(PropertyChangeEvent e) { public void propertyChange(PropertyChangeEvent e) {
@@ -565,12 +535,11 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
} }
} }
} }
/** /**
* Removes a parser. * Removes a parser.
* *
* @param parser * @param parser The parser to remove.
* The parser to remove.
* @return Whether the parser was found. * @return Whether the parser was found.
* @see #addParser(Parser) * @see #addParser(Parser)
* @see #getParser(int) * @see #getParser(int)
@@ -583,13 +552,12 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
} }
return removed; return removed;
} }
/** /**
* Removes all parser notices (and clears highlights in the editor) from * Removes all parser notices (and clears highlights in the editor) from a
* a particular parser. * particular parser.
* *
* @param parser * @param parser The parser.
* The parser.
*/ */
private void removeParserNotices(Parser parser) { private void removeParserNotices(Parser parser) {
if (noticeHighlightPairs != null) { if (noticeHighlightPairs != null) {
@@ -603,14 +571,13 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
} }
} }
} }
/** /**
* Removes any currently stored notices (and the corresponding highlights * Removes any currently stored notices (and the corresponding highlights from
* from the editor) from the same Parser, and in the given line range, * the editor) from the same Parser, and in the given line range, as in the
* as in the results. * results.
* *
* @param res * @param res The results.
* The results.
*/ */
private void removeParserNotices(ParseResult res) { private void removeParserNotices(ParseResult res) {
if (noticeHighlightPairs != null) { if (noticeHighlightPairs != null) {
@@ -632,12 +599,11 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
} }
} }
} }
/** /**
* Called when the document is modified. * Called when the document is modified.
* *
* @param e * @param e The document event.
* The document event.
*/ */
@Override @Override
public void removeUpdate(DocumentEvent e) { public void removeUpdate(DocumentEvent e) {
@@ -658,7 +624,7 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
} }
handleDocumentEvent(e); handleDocumentEvent(e);
} }
/** /**
* Restarts parsing the document. * Restarts parsing the document.
* *
@@ -668,14 +634,13 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
timer.restart(); timer.restart();
running = true; running = true;
} }
/** /**
* Sets the delay between the last "concurrent" edit and when the document * Sets the delay between the last "concurrent" edit and when the document is
* is re-parsed. * re-parsed.
* *
* @param millis * @param millis The new delay, in milliseconds. This must be greater than
* The new delay, in milliseconds. This must be greater * <code>0</code>.
* than <code>0</code>.
* @see #getDelay() * @see #getDelay()
*/ */
public void setDelay(int millis) { public void setDelay(int millis) {
@@ -688,20 +653,18 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
timer.start(); timer.start();
} }
} }
/** /**
* Returns whether a parser notice should be removed, based on a parse * Returns whether a parser notice should be removed, based on a parse result.
* result.
* *
* @param notice * @param notice The notice in question.
* The notice in question. * @param res The result.
* @param res
* The result.
* @return Whether the notice should be removed. * @return Whether the notice should be removed.
*/ */
private boolean shouldRemoveNotice(ParserNotice notice, ParseResult res) { private boolean shouldRemoveNotice(ParserNotice notice, ParseResult res) {
if (DEBUG_PARSING) { if (DEBUG_PARSING) {
System.out.println("[DEBUG]: ... ... shouldRemoveNotice " + notice + ": " + (notice.getParser() == res.getParser())); System.out.println(
"[DEBUG]: ... ... shouldRemoveNotice " + notice + ": " + (notice.getParser() == res.getParser()));
} }
// NOTE: We must currently remove all notices for the parser. Parser // NOTE: We must currently remove all notices for the parser. Parser
// implementors are required to parse the entire document each parsing // implementors are required to parse the entire document each parsing
@@ -712,7 +675,7 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
// return same_parser && (in_reparsed_range || in_deleted_end_of_doc) // return same_parser && (in_reparsed_range || in_deleted_end_of_doc)
return notice.getParser() == res.getParser(); return notice.getParser() == res.getParser();
} }
/** /**
* Stops parsing the document. * Stops parsing the document.
* *
@@ -722,21 +685,21 @@ class ParserManager implements DocumentListener, ActionListener, HyperlinkListen
timer.stop(); timer.stop();
running = false; running = false;
} }
/** /**
* Mapping of a parser notice to its highlight in the editor. * Mapping of a parser notice to its highlight in the editor.
*/ */
private static class NoticeHighlightPair { private static class NoticeHighlightPair {
private ParserNotice notice; private ParserNotice notice;
private HighlightInfo highlight; private HighlightInfo highlight;
NoticeHighlightPair(ParserNotice notice, HighlightInfo highlight) { NoticeHighlightPair(ParserNotice notice, HighlightInfo highlight) {
this.notice = notice; this.notice = notice;
this.highlight = highlight; this.highlight = highlight;
} }
} }
static { static {
boolean debugParsing = false; boolean debugParsing = false;
try { try {
@@ -12,48 +12,45 @@ import javax.swing.JWindow;
/** /**
* A hook allowing hosting applications to decorate JWindows created by the * A hook allowing hosting applications to decorate JWindows created by the
* AutoComplete library. For example, you could use the * AutoComplete library. For example, you could use the
* <a href="http://jgoodies.com/">JGoodies</a> library to add drop shadows * <a href="http://jgoodies.com/">JGoodies</a> library to add drop shadows to
* to the windows. * the windows.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public abstract class PopupWindowDecorator { public abstract class PopupWindowDecorator {
/** /**
* The singleton instance of this class. * The singleton instance of this class.
*/ */
private static PopupWindowDecorator decorator; private static PopupWindowDecorator decorator;
/** /**
* Callback called whenever an appropriate JWindow is created by the * Callback called whenever an appropriate JWindow is created by the
* AutoComplete library. Implementations can decorate the window however * AutoComplete library. Implementations can decorate the window however they
* they see fit. * see fit.
* *
* @param window * @param window The newly-created window.
* The newly-created window.
*/ */
public abstract void decorate(JWindow window); public abstract void decorate(JWindow window);
/** /**
* Returns the singleton instance of this class. This should only be * Returns the singleton instance of this class. This should only be called on
* called on the EDT. * the EDT.
* *
* @return The singleton instance of this class, or <code>null</code> * @return The singleton instance of this class, or <code>null</code> for none.
* for none.
* @see #set(PopupWindowDecorator) * @see #set(PopupWindowDecorator)
*/ */
public static PopupWindowDecorator get() { public static PopupWindowDecorator get() {
return decorator; return decorator;
} }
/** /**
* Sets the singleton instance of this class. This should only be called * Sets the singleton instance of this class. This should only be called on the
* on the EDT. * EDT.
* *
* @param decorator * @param decorator The new instance of this class. This may be
* The new instance of this class. This may be * <code>null</code>.
* <code>null</code>.
* @see #get() * @see #get()
*/ */
public static void set(PopupWindowDecorator decorator) { public static void set(PopupWindowDecorator decorator) {
+20 -28
View File
@@ -17,46 +17,38 @@ import javax.swing.text.BadLocationException;
* @version 1.0 * @version 1.0
*/ */
interface RSTAView { interface RSTAView {
/** /**
* Returns the y-coordinate of the specified line. * Returns the y-coordinate of the specified line.
* <p> * <p>
* *
* This method is quicker than using traditional * This method is quicker than using traditional <code>modelToView(int)</code>
* <code>modelToView(int)</code> calls, as the entire bounding box isn't * calls, as the entire bounding box isn't computed.
* computed.
* *
* @param alloc * @param alloc The area the text area can render into.
* The area the text area can render into. * @param line The line number.
* @param line * @return The y-coordinate of the top of the line, or <code>-1</code> if this
* The line number. * text area doesn't yet have a positive size or the line is hidden
* @return The y-coordinate of the top of the line, or <code>-1</code> if * (i.e. from folding).
* this text area doesn't yet have a positive size or the line is * @throws BadLocationException If <code>line</code> isn't a valid line number
* hidden (i.e. from folding). * for this document.
* @throws BadLocationException
* If <code>line</code> isn't a valid line
* number for this document.
*/ */
int yForLine(Rectangle alloc, int line) throws BadLocationException; int yForLine(Rectangle alloc, int line) throws BadLocationException;
/** /**
* Returns the y-coordinate of the line containing a specified offset. * Returns the y-coordinate of the line containing a specified offset.
* <p> * <p>
* *
* This method is quicker than using traditional * This method is quicker than using traditional <code>modelToView(int)</code>
* <code>modelToView(int)</code> calls, as the entire bounding box isn't * calls, as the entire bounding box isn't computed.
* computed.
* *
* @param alloc * @param alloc The area the text area can render into.
* The area the text area can render into. * @param offs The offset info the document.
* @param offs * @return The y-coordinate of the top of the offset, or <code>-1</code> if this
* The offset info the document. * text area doesn't yet have a positive size or the line is hidden
* @return The y-coordinate of the top of the offset, or <code>-1</code> if * (i.e. from folding).
* this text area doesn't yet have a positive size or the line is * @throws BadLocationException If <code>offs</code> isn't a valid offset into
* hidden (i.e. from folding). * the document.
* @throws BadLocationException
* If <code>offs</code> isn't a valid offset
* into the document.
*/ */
int yForLineContaining(Rectangle alloc, int offs) throws BadLocationException; int yForLineContaining(Rectangle alloc, int offs) throws BadLocationException;
} }
@@ -49,10 +49,9 @@ import me.ByteEdit.edit.JavaAssemblyTokenMaker;
* @version 1.0 * @version 1.0
*/ */
public class RSyntaxDocument extends RDocument implements Iterable<Token>, SyntaxConstants { public class RSyntaxDocument extends RDocument implements Iterable<Token>, SyntaxConstants {
/** /**
* Creates a {@link TokenMaker} appropriate for a given programming * Creates a {@link TokenMaker} appropriate for a given programming language.
* language.
*/ */
private transient TokenMakerFactory tokenMakerFactory; private transient TokenMakerFactory tokenMakerFactory;
/** /**
@@ -64,8 +63,7 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
*/ */
private String syntaxStyle; private String syntaxStyle;
/** /**
* Array of values representing the "last token type" on each line. This is * Array of values representing the "last token type" on each line. This is used
* used
* in cases such as multi-line comments: if the previous line ended with an * in cases such as multi-line comments: if the previous line ended with an
* (unclosed) multi-line comment, we can use this knowledge and start the * (unclosed) multi-line comment, we can use this knowledge and start the
* current line's syntax highlighting in multi-line comment state. * current line's syntax highlighting in multi-line comment state.
@@ -77,35 +75,28 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
private transient int tokenRetrievalCount = 0; private transient int tokenRetrievalCount = 0;
private transient Segment s; private transient Segment s;
/** /**
* If this is set to <code>true</code>, debug information about how much * If this is set to <code>true</code>, debug information about how much token
* token
* caching is helping is printed to stdout. * caching is helping is printed to stdout.
*/ */
private static final boolean DEBUG_TOKEN_CACHING = false; private static final boolean DEBUG_TOKEN_CACHING = false;
/** /**
* Constructs a plain text document. A default root element is created, and * Constructs a plain text document. A default root element is created, and the
* the
* tab size set to 5. * tab size set to 5.
* *
* @param syntaxStyle * @param syntaxStyle The syntax highlighting scheme to use.
* The syntax highlighting scheme to use.
*/ */
public RSyntaxDocument(String syntaxStyle) { public RSyntaxDocument(String syntaxStyle) {
this(null, syntaxStyle); this(null, syntaxStyle);
} }
/** /**
* Constructs a plain text document. A default root element is created, and * Constructs a plain text document. A default root element is created, and the
* the
* tab size set to 5. * tab size set to 5.
* *
* @param tmf * @param tmf The <code>TokenMakerFactory</code> for this document. If
* The <code>TokenMakerFactory</code> for this document. If this * this is <code>null</code>, a default factory is used.
* is * @param syntaxStyle The syntax highlighting scheme to use.
* <code>null</code>, a default factory is used.
* @param syntaxStyle
* The syntax highlighting scheme to use.
*/ */
public RSyntaxDocument(TokenMakerFactory tmf, String syntaxStyle) { public RSyntaxDocument(TokenMakerFactory tmf, String syntaxStyle) {
putProperty(tabSizeAttribute, Integer.valueOf(5)); putProperty(tabSizeAttribute, Integer.valueOf(5));
@@ -115,27 +106,23 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
setTokenMakerFactory(tmf); setTokenMakerFactory(tmf);
setSyntaxStyle(syntaxStyle); setSyntaxStyle(syntaxStyle);
} }
/** /**
* Alerts all listeners to this document of an insertion. This is overridden * Alerts all listeners to this document of an insertion. This is overridden so
* so
* we can update our syntax highlighting stuff. * we can update our syntax highlighting stuff.
* <p> * <p>
* The syntax highlighting stuff has to be here instead of in * The syntax highlighting stuff has to be here instead of in
* <code>insertUpdate</code> because <code>insertUpdate</code> is not called * <code>insertUpdate</code> because <code>insertUpdate</code> is not called by
* by
* the undo/redo actions, but this method is. * the undo/redo actions, but this method is.
* *
* @param e * @param e The change.
* The change.
*/ */
@Override @Override
protected void fireInsertUpdate(DocumentEvent e) { protected void fireInsertUpdate(DocumentEvent e) {
cachedTokenList = null; cachedTokenList = null;
/* /*
* Now that the text is actually inserted into the content and element * Now that the text is actually inserted into the content and element
* structure, we can update our token elements and * structure, we can update our token elements and "last tokens on lines"
* "last tokens on lines"
* structure. * structure.
*/ */
Element lineMap = getDefaultRootElement(); Element lineMap = getDefaultRootElement();
@@ -174,23 +161,20 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
// Let all listeners know about the insertion. // Let all listeners know about the insertion.
super.fireInsertUpdate(e); super.fireInsertUpdate(e);
} }
/** /**
* This method is called AFTER the content has been inserted into the * This method is called AFTER the content has been inserted into the document
* document
* and the element structure has been updated. * and the element structure has been updated.
* <p> * <p>
* The syntax-highlighting updates need to be done here (as opposed to an * The syntax-highlighting updates need to be done here (as opposed to an
* override of <code>postRemoveUpdate</code>) as this method is called in * override of <code>postRemoveUpdate</code>) as this method is called in
* response to undo/redo events, whereas <code>postRemoveUpdate</code> is * response to undo/redo events, whereas <code>postRemoveUpdate</code> is not.
* not.
* <p> * <p>
* Now that the text is actually inserted into the content and element * Now that the text is actually inserted into the content and element
* structure, we can update our token elements and "last tokens on lines" * structure, we can update our token elements and "last tokens on lines"
* structure. * structure.
* *
* @param chng * @param chng The change that occurred.
* The change that occurred.
* @see #removeUpdate * @see #removeUpdate
*/ */
@Override @Override
@@ -240,26 +224,22 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
// Let all of our listeners know about the removal. // Let all of our listeners know about the removal.
super.fireRemoveUpdate(chng); super.fireRemoveUpdate(chng);
} }
/** /**
* Returns the closest {@link TokenTypes "standard" token type} for a given * Returns the closest {@link TokenTypes "standard" token type} for a given
* "internal" token type (e.g. one whose value is <code>&lt; 0</code>). * "internal" token type (e.g. one whose value is <code>&lt; 0</code>).
* *
* @param type * @param type The token type.
* The token type. * @return The closest "standard" token type. If a mapping is not defined for
* @return The closest "standard" token type. If a mapping is not defined
* for
* this language, then <code>type</code> is returned. * this language, then <code>type</code> is returned.
*/ */
public int getClosestStandardTokenTypeForInternalType(int type) { public int getClosestStandardTokenTypeForInternalType(int type) {
return tokenMaker.getClosestStandardTokenTypeForInternalType(type); return tokenMaker.getClosestStandardTokenTypeForInternalType(type);
} }
/** /**
* Returns whether closing markup tags should be automatically completed. * Returns whether closing markup tags should be automatically completed. This
* This * method only returns <code>true</code> if {@link #getLanguageIsMarkup()} also
* method only returns <code>true</code> if {@link #getLanguageIsMarkup()}
* also
* returns <code>true</code>. * returns <code>true</code>.
* *
* @return Whether markup closing tags should be automatically completed. * @return Whether markup closing tags should be automatically completed.
@@ -269,26 +249,24 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
// TODO: Remove terrible dependency on AbstractMarkupTokenMaker // TODO: Remove terrible dependency on AbstractMarkupTokenMaker
return getLanguageIsMarkup() && ((AbstractMarkupTokenMaker) tokenMaker).getCompleteCloseTags(); return getLanguageIsMarkup() && ((AbstractMarkupTokenMaker) tokenMaker).getCompleteCloseTags();
} }
/** /**
* Returns whether the current programming language uses curly braces * Returns whether the current programming language uses curly braces
* ('<code>{</code>' and '<code>}</code>') to denote code blocks. * ('<code>{</code>' and '<code>}</code>') to denote code blocks.
* *
* @param languageIndex * @param languageIndex The language index at the offset in question. Since some
* The language index at the offset in question. Since some * <code>TokenMaker</code>s effectively have nested
* <code>TokenMaker</code>s effectively have nested languages * languages (such as JavaScript in HTML), this parameter
* (such * tells the <code>TokenMaker</code> what sub-language to
* as JavaScript in HTML), this parameter tells the * look at.
* <code>TokenMaker</code> what sub-language to look at.
* @return Whether curly braces denote code blocks. * @return Whether curly braces denote code blocks.
*/ */
public boolean getCurlyBracesDenoteCodeBlocks(int languageIndex) { public boolean getCurlyBracesDenoteCodeBlocks(int languageIndex) {
return tokenMaker.getCurlyBracesDenoteCodeBlocks(languageIndex); return tokenMaker.getCurlyBracesDenoteCodeBlocks(languageIndex);
} }
/** /**
* Returns whether the current language is a markup language, such as HTML, * Returns whether the current language is a markup language, such as HTML, XML
* XML
* or PHP. * or PHP.
* *
* @return Whether the current language is a markup language. * @return Whether the current language is a markup language.
@@ -296,50 +274,42 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
public boolean getLanguageIsMarkup() { public boolean getLanguageIsMarkup() {
return tokenMaker.isMarkupLanguage(); return tokenMaker.isMarkupLanguage();
} }
/** /**
* Returns the token type of the last token on the given line. * Returns the token type of the last token on the given line.
* *
* @param line * @param line The line to inspect.
* The line to inspect. * @return The token type of the last token on the specified line. If the line
* @return The token type of the last token on the specified line. If the
* line
* is invalid, an exception is thrown. * is invalid, an exception is thrown.
*/ */
public int getLastTokenTypeOnLine(int line) { public int getLastTokenTypeOnLine(int line) {
return lastTokensOnLines.get(line); return lastTokensOnLines.get(line);
} }
/** /**
* Returns the text to place at the beginning and end of a line to "comment" * Returns the text to place at the beginning and end of a line to "comment" it
* it
* in this programming language. * in this programming language.
* *
* @return The start and end strings to add to a line to "comment" it out. A * @return The start and end strings to add to a line to "comment" it out. A
* <code>null</code> value for either means there is no string to * <code>null</code> value for either means there is no string to add
* add * for that part. A value of <code>null</code> for the array means this
* for that part. A value of <code>null</code> for the array means
* this
* language does not support commenting/uncommenting lines. * language does not support commenting/uncommenting lines.
*/ */
public String[] getLineCommentStartAndEnd(int languageIndex) { public String[] getLineCommentStartAndEnd(int languageIndex) {
return tokenMaker.getLineCommentStartAndEnd(languageIndex); return tokenMaker.getLineCommentStartAndEnd(languageIndex);
} }
/** /**
* Returns whether tokens of the specified type should have "mark * Returns whether tokens of the specified type should have "mark occurrences"
* occurrences"
* enabled for the current programming language. * enabled for the current programming language.
* *
* @param type * @param type The token type.
* The token type. * @return Whether tokens of this type should have "mark occurrences" enabled.
* @return Whether tokens of this type should have "mark occurrences"
* enabled.
*/ */
boolean getMarkOccurrencesOfTokenType(int type) { boolean getMarkOccurrencesOfTokenType(int type) {
return tokenMaker.getMarkOccurrencesOfTokenType(type); return tokenMaker.getMarkOccurrencesOfTokenType(type);
} }
/** /**
* Returns the occurrence marker for the current language. * Returns the occurrence marker for the current language.
* *
@@ -348,13 +318,12 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
OccurrenceMarker getOccurrenceMarker() { OccurrenceMarker getOccurrenceMarker() {
return tokenMaker.getOccurrenceMarker(); return tokenMaker.getOccurrenceMarker();
} }
/** /**
* This method returns whether auto indentation should be done if Enter is * This method returns whether auto indentation should be done if Enter is
* pressed at the end of the specified line. * pressed at the end of the specified line.
* *
* @param line * @param line The line to check.
* The line to check.
* @return Whether an extra indentation should be done. * @return Whether an extra indentation should be done.
*/ */
public boolean getShouldIndentNextLine(int line) { public boolean getShouldIndentNextLine(int line) {
@@ -362,7 +331,7 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
t = t.getLastNonCommentNonWhitespaceToken(); t = t.getLastNonCommentNonWhitespaceToken();
return tokenMaker.getShouldIndentNextLineAfter(t); return tokenMaker.getShouldIndentNextLineAfter(t);
} }
/** /**
* Returns the syntax style being used. * Returns the syntax style being used.
* *
@@ -372,16 +341,14 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
public String getSyntaxStyle() { public String getSyntaxStyle() {
return syntaxStyle; return syntaxStyle;
} }
/** /**
* Returns a token list for the specified segment of text representing the * Returns a token list for the specified segment of text representing the
* specified line number. This method is basically a wrapper for * specified line number. This method is basically a wrapper for
* <code>tokenMaker.getTokenList</code> that takes into account the last * <code>tokenMaker.getTokenList</code> that takes into account the last token
* token
* on the previous line to assure token accuracy. * on the previous line to assure token accuracy.
* *
* @param line * @param line The line number of <code>text</code> in the document, &gt;= 0.
* The line number of <code>text</code> in the document, &gt;= 0.
* @return A token list representing the specified line. * @return A token list representing the specified line.
*/ */
public final Token getTokenListForLine(int line) { public final Token getTokenListForLine(int line) {
@@ -412,7 +379,7 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
cachedTokenList = tokenMaker.getTokenList(s, initialTokenType, startOffset); cachedTokenList = tokenMaker.getTokenList(s, initialTokenType, startOffset);
return cachedTokenList; return cachedTokenList;
} }
boolean insertBreakSpecialHandling(ActionEvent e) { boolean insertBreakSpecialHandling(ActionEvent e) {
Action a = tokenMaker.getInsertBreakAction(); Action a = tokenMaker.getInsertBreakAction();
if (a != null) { if (a != null) {
@@ -421,28 +388,23 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
} }
return false; return false;
} }
/** /**
* Returns whether a character could be part of an "identifier" token in a * Returns whether a character could be part of an "identifier" token in a
* specific language. This is used to identify such things as the bounds of * specific language. This is used to identify such things as the bounds of the
* the
* "word" to select on double-clicking. * "word" to select on double-clicking.
* *
* @param languageIndex * @param languageIndex The language index the character was found in.
* The language index the character was found in. * @param ch The character.
* @param ch
* The character.
* @return Whether the character could be part of an "identifier" token. * @return Whether the character could be part of an "identifier" token.
*/ */
public boolean isIdentifierChar(int languageIndex, char ch) { public boolean isIdentifierChar(int languageIndex, char ch) {
return tokenMaker.isIdentifierChar(languageIndex, ch); return tokenMaker.isIdentifierChar(languageIndex, ch);
} }
/** /**
* Returns an iterator over the paintable tokens in this document. Results * Returns an iterator over the paintable tokens in this document. Results are
* are * undefined if this document is modified while the iterator is being iterated
* undefined if this document is modified while the iterator is being
* iterated
* through, so this should only be used on the EDT. * through, so this should only be used on the EDT.
* <p> * <p>
* *
@@ -455,12 +417,11 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
public Iterator<Token> iterator() { public Iterator<Token> iterator() {
return new TokenIterator(this); return new TokenIterator(this);
} }
/** /**
* Deserializes a document. * Deserializes a document.
* *
* @param in * @param in The stream to read from.
* The stream to read from.
* @throws ClassNotFoundException * @throws ClassNotFoundException
* @throws IOException * @throws IOException
*/ */
@@ -476,16 +437,13 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
lastTokensOnLines = new DynamicIntArray(lineCount); lastTokensOnLines = new DynamicIntArray(lineCount);
setSyntaxStyle(syntaxStyle); // Actually install (transient) TokenMaker setSyntaxStyle(syntaxStyle); // Actually install (transient) TokenMaker
} }
/** /**
* Makes our private <code>Segment s</code> point to the text in our * Makes our private <code>Segment s</code> point to the text in our document
* document * referenced by the specified element. Note that <code>line</code> MUST be a
* referenced by the specified element. Note that <code>line</code> MUST be
* a
* valid line number in the document. * valid line number in the document.
* *
* @param line * @param line The line number you want to get.
* The line number you want to get.
*/ */
private void setSharedSegment(int line) { private void setSharedSegment(int line) {
Element map = getDefaultRootElement(); Element map = getDefaultRootElement();
@@ -504,20 +462,17 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
throw new InternalError("Text range not in document: " + startOffset + "-" + endOffset); throw new InternalError("Text range not in document: " + startOffset + "-" + endOffset);
} }
} }
/** /**
* Sets the syntax style being used for syntax highlighting in this * Sets the syntax style being used for syntax highlighting in this document.
* document.
* What styles are supported by a document is determined by its * What styles are supported by a document is determined by its
* {@link TokenMakerFactory}. By default, all <code>RSyntaxDocument</code>s * {@link TokenMakerFactory}. By default, all <code>RSyntaxDocument</code>s
* support all languages built into <code>RSyntaxTextArea</code>. * support all languages built into <code>RSyntaxTextArea</code>.
* *
* @param styleKey * @param styleKey The new style to use, such as
* The new style to use, such as * {@link SyntaxConstants#SYNTAX_STYLE_JAVA}. If this style is
* {@link SyntaxConstants#SYNTAX_STYLE_JAVA}. If this style is * not known or supported by this document, then
* not * {@link SyntaxConstants#SYNTAX_STYLE_NONE} is used.
* known or supported by this document, then
* {@link SyntaxConstants#SYNTAX_STYLE_NONE} is used.
* @see #setSyntaxStyle(TokenMaker) * @see #setSyntaxStyle(TokenMaker)
* @see #getSyntaxStyle() * @see #getSyntaxStyle()
*/ */
@@ -530,15 +485,13 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
updateSyntaxHighlightingInformation(); updateSyntaxHighlightingInformation();
this.syntaxStyle = styleKey; this.syntaxStyle = styleKey;
} }
/** /**
* Sets the syntax style being used for syntax highlighting in this * Sets the syntax style being used for syntax highlighting in this document.
* document.
* You should call this method if you've created a custom token maker for a * You should call this method if you've created a custom token maker for a
* language not normally supported by <code>RSyntaxTextArea</code>. * language not normally supported by <code>RSyntaxTextArea</code>.
* *
* @param tokenMaker * @param tokenMaker The new token maker to use.
* The new token maker to use.
* @see #setSyntaxStyle(String) * @see #setSyntaxStyle(String)
*/ */
public void setSyntaxStyle(TokenMaker tokenMaker) { public void setSyntaxStyle(TokenMaker tokenMaker) {
@@ -546,35 +499,28 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
updateSyntaxHighlightingInformation(); updateSyntaxHighlightingInformation();
this.syntaxStyle = "text/unknown"; // TODO: Make me public? this.syntaxStyle = "text/unknown"; // TODO: Make me public?
} }
/** /**
* Sets the token maker factory used by this document. * Sets the token maker factory used by this document.
* *
* @param tmf * @param tmf The <code>TokenMakerFactory</code> for this document. If this is
* The <code>TokenMakerFactory</code> for this document. If this
* is
* <code>null</code>, a default factory is used. * <code>null</code>, a default factory is used.
*/ */
public void setTokenMakerFactory(TokenMakerFactory tmf) { public void setTokenMakerFactory(TokenMakerFactory tmf) {
tokenMakerFactory = tmf != null ? tmf : TokenMakerFactory.getDefaultInstance(); tokenMakerFactory = tmf != null ? tmf : TokenMakerFactory.getDefaultInstance();
} }
/** /**
* Loops through the last-tokens-on-lines array from a specified point * Loops through the last-tokens-on-lines array from a specified point onward,
* onward, * updating last-token values until they stop changing. This should be called
* updating last-token values until they stop changing. This should be * when lines are updated/inserted/removed, as doing so may cause lines below to
* called
* when lines are updated/inserted/removed, as doing so may cause lines
* below to
* change color. * change color.
* *
* @param line * @param line The first line to check for a change in last-token
* The first line to check for a change in last-token value. * value.
* @param numLines * @param numLines The number of lines in the document.
* The number of lines in the document. * @param previousTokenType The last-token value of the line just before
* @param previousTokenType * <code>line</code>.
* The last-token value of the line just before
* <code>line</code>.
* @return The last line that needs repainting. * @return The last line that needs repainting.
*/ */
private int updateLastTokensBelow(int line, int numLines, int previousTokenType) { private int updateLastTokensBelow(int line, int numLines, int previousTokenType) {
@@ -627,7 +573,7 @@ public class RSyntaxDocument extends RDocument implements Iterable<Token>, Synta
} }
return line; return line;
} }
/** /**
* Updates internal state information; e.g. the "last tokens on lines" data. * Updates internal state information; e.g. the "last tokens on lines" data.
* After this, a changed update is fired to let listeners know that the * After this, a changed update is fired to let listeners know that the
File diff suppressed because it is too large. Load diff
@@ -27,8 +27,8 @@ import org.fife.ui.rtextarea.SmartHighlightPainter;
/** /**
* The highlighter implementation used by {@link RSyntaxTextArea}s. It knows to * The highlighter implementation used by {@link RSyntaxTextArea}s. It knows to
* always paint "marked occurrences" highlights below selection highlights, * always paint "marked occurrences" highlights below selection highlights, and
* and squiggle underline highlights above all other highlights. * squiggle underline highlights above all other highlights.
* <p> * <p>
* *
* Most of this code is copied from javax.swing.text.DefaultHighlighter; * Most of this code is copied from javax.swing.text.DefaultHighlighter;
@@ -38,22 +38,22 @@ import org.fife.ui.rtextarea.SmartHighlightPainter;
* @version 1.0 * @version 1.0
*/ */
public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter { public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
/** /**
* Marked occurrences in the document (to be painted separately from * Marked occurrences in the document (to be painted separately from other
* other highlights). * highlights).
*/ */
private List<SyntaxLayeredHighlightInfoImpl> markedOccurrences; private List<SyntaxLayeredHighlightInfoImpl> markedOccurrences;
/** /**
* Highlights from document parsers. These should be painted "on top of" * Highlights from document parsers. These should be painted "on top of" all
* all other highlights to ensure they are always above the selection. * other highlights to ensure they are always above the selection.
*/ */
private List<SyntaxLayeredHighlightInfoImpl> parserHighlights; private List<SyntaxLayeredHighlightInfoImpl> parserHighlights;
/** /**
* The default color used for parser notices when none is specified. * The default color used for parser notices when none is specified.
*/ */
private static final Color DEFAULT_PARSER_NOTICE_COLOR = Color.RED; private static final Color DEFAULT_PARSER_NOTICE_COLOR = Color.RED;
/** /**
* Constructor. * Constructor.
*/ */
@@ -62,7 +62,7 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
parserHighlights = new ArrayList<SyntaxLayeredHighlightInfoImpl>(0); // Often parserHighlights = new ArrayList<SyntaxLayeredHighlightInfoImpl>(0); // Often
// unused // unused
} }
/** /**
* Adds a special "marked occurrence" highlight. * Adds a special "marked occurrence" highlight.
* *
@@ -88,12 +88,11 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
mapper.damageRange(textArea, start, end); mapper.damageRange(textArea, start, end);
return i; return i;
} }
/** /**
* Adds a highlight from a parser. * Adds a highlight from a parser.
* *
* @param notice * @param notice The notice from a {@link Parser}.
* The notice from a {@link Parser}.
* @return A tag with which to reference the highlight. * @return A tag with which to reference the highlight.
* @throws BadLocationException * @throws BadLocationException
* @see #clearParserHighlights() * @see #clearParserHighlights()
@@ -128,7 +127,7 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
mapper.damageRange(textArea, start, end); mapper.damageRange(textArea, start, end);
return i; return i;
} }
/** /**
* Removes all "marked occurrences" highlights from the view. * Removes all "marked occurrences" highlights from the view.
* *
@@ -142,7 +141,7 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
} }
markedOccurrences.clear(); markedOccurrences.clear();
} }
/** /**
* Removes all parser highlights. * Removes all parser highlights.
* *
@@ -157,12 +156,11 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
} }
parserHighlights.clear(); parserHighlights.clear();
} }
/** /**
* Removes all of the highlights for a specific parser. * Removes all of the highlights for a specific parser.
* *
* @param parser * @param parser The parser.
* The parser.
*/ */
public void clearParserHighlights(Parser parser) { public void clearParserHighlights(Parser parser) {
Iterator<SyntaxLayeredHighlightInfoImpl> i = parserHighlights.iterator(); Iterator<SyntaxLayeredHighlightInfoImpl> i = parserHighlights.iterator();
@@ -176,7 +174,7 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
} }
} }
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -186,10 +184,10 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
markedOccurrences.clear(); markedOccurrences.clear();
parserHighlights.clear(); parserHighlights.clear();
} }
/** /**
* Returns a list of "marked occurrences" in the text area. If there are * Returns a list of "marked occurrences" in the text area. If there are no
* no marked occurrences, this will be an empty list. * marked occurrences, this will be an empty list.
* *
* @return The list of marked occurrences, or an empty list if none. The * @return The list of marked occurrences, or an empty list if none. The
* contents of this list will be of type {@link DocumentRange}. * contents of this list will be of type {@link DocumentRange}.
@@ -210,19 +208,19 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
} }
return list; return list;
} }
@Override @Override
public void paintLayeredHighlights(Graphics g, int lineStart, int lineEnd, Shape viewBounds, JTextComponent editor, View view) { public void paintLayeredHighlights(Graphics g, int lineStart, int lineEnd, Shape viewBounds, JTextComponent editor,
View view) {
paintListLayered(g, lineStart, lineEnd, viewBounds, editor, view, markedOccurrences); paintListLayered(g, lineStart, lineEnd, viewBounds, editor, view, markedOccurrences);
super.paintLayeredHighlights(g, lineStart, lineEnd, viewBounds, editor, view); super.paintLayeredHighlights(g, lineStart, lineEnd, viewBounds, editor, view);
paintListLayered(g, lineStart, lineEnd, viewBounds, editor, view, parserHighlights); paintListLayered(g, lineStart, lineEnd, viewBounds, editor, view, parserHighlights);
} }
/** /**
* Removes a parser highlight from this view. * Removes a parser highlight from this view.
* *
* @param tag * @param tag The reference to the highlight.
* The reference to the highlight.
* @see #addParserHighlight(ParserNotice, * @see #addParserHighlight(ParserNotice,
* javax.swing.text.Highlighter.HighlightPainter) * javax.swing.text.Highlighter.HighlightPainter)
*/ */
@@ -230,16 +228,15 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
repaintListHighlight(tag); repaintListHighlight(tag);
parserHighlights.remove(tag); parserHighlights.remove(tag);
} }
/** /**
* Highlight info implementation used for parser notices and marked * Highlight info implementation used for parser notices and marked occurrences.
* occurrences.
*/ */
private static class SyntaxLayeredHighlightInfoImpl extends LayeredHighlightInfoImpl { private static class SyntaxLayeredHighlightInfoImpl extends LayeredHighlightInfoImpl {
private ParserNotice notice;// Color color; // Used only by Parser private ParserNotice notice;// Color color; // Used only by Parser
// highlights. // highlights.
@Override @Override
public Color getColor() { public Color getColor() {
// return color; // return color;
@@ -252,11 +249,11 @@ public class RSyntaxTextAreaHighlighter extends RTextAreaHighlighter {
} }
return color; return color;
} }
@Override @Override
public String toString() { public String toString() {
return "[SyntaxLayeredHighlightInfoImpl: " + "startOffs=" + getStartOffset() + ", endOffs=" + getEndOffset() + ", color=" return "[SyntaxLayeredHighlightInfoImpl: " + "startOffs=" + getStartOffset() + ", endOffs=" + getEndOffset()
+ getColor() + "]"; + ", color=" + getColor() + "]";
} }
} }
} }
@@ -27,34 +27,33 @@ import org.fife.ui.rtextarea.RTextArea;
import org.fife.ui.rtextarea.RTextAreaUI; import org.fife.ui.rtextarea.RTextAreaUI;
/** /**
* UI used by <code>RSyntaxTextArea</code>. This allows us to implement * UI used by <code>RSyntaxTextArea</code>. This allows us to implement syntax
* syntax highlighting. * highlighting.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 0.1 * @version 0.1
*/ */
public class RSyntaxTextAreaUI extends RTextAreaUI { public class RSyntaxTextAreaUI extends RTextAreaUI {
private static final String SHARED_ACTION_MAP_NAME = "RSyntaxTextAreaUI.actionMap"; private static final String SHARED_ACTION_MAP_NAME = "RSyntaxTextAreaUI.actionMap";
private static final String SHARED_INPUT_MAP_NAME = "RSyntaxTextAreaUI.inputMap"; private static final String SHARED_INPUT_MAP_NAME = "RSyntaxTextAreaUI.inputMap";
private static final EditorKit DEFAULT_KIT = new RSyntaxTextAreaEditorKit(); private static final EditorKit DEFAULT_KIT = new RSyntaxTextAreaEditorKit();
public static ComponentUI createUI(JComponent ta) { public static ComponentUI createUI(JComponent ta) {
return new RSyntaxTextAreaUI(ta); return new RSyntaxTextAreaUI(ta);
} }
/** /**
* Constructor. * Constructor.
*/ */
public RSyntaxTextAreaUI(JComponent rSyntaxTextArea) { public RSyntaxTextAreaUI(JComponent rSyntaxTextArea) {
super(rSyntaxTextArea); super(rSyntaxTextArea);
} }
/** /**
* Creates the view for an element. * Creates the view for an element.
* *
* @param elem * @param elem The element.
* The element.
* @return The view. * @return The view.
*/ */
@Override @Override
@@ -72,7 +71,7 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
} }
return null; return null;
} }
/** /**
* Creates the highlighter to use for syntax text areas. * Creates the highlighter to use for syntax text areas.
* *
@@ -82,11 +81,11 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
protected Highlighter createHighlighter() { protected Highlighter createHighlighter() {
return new RSyntaxTextAreaHighlighter(); return new RSyntaxTextAreaHighlighter();
} }
/** /**
* Returns the name to use to cache/fetch the shared action map. This * Returns the name to use to cache/fetch the shared action map. This should be
* should be overridden by subclasses if the subclass has its own custom * overridden by subclasses if the subclass has its own custom editor kit to
* editor kit to install, so its actions get picked up. * install, so its actions get picked up.
* *
* @return The name of the cached action map. * @return The name of the cached action map.
*/ */
@@ -94,12 +93,11 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
protected String getActionMapName() { protected String getActionMapName() {
return SHARED_ACTION_MAP_NAME; return SHARED_ACTION_MAP_NAME;
} }
/** /**
* Fetches the EditorKit for the UI. * Fetches the EditorKit for the UI.
* *
* @param tc * @param tc The text component for which this UI is installed.
* The text component for which this UI is installed.
* @return The editor capabilities. * @return The editor capabilities.
* @see javax.swing.plaf.TextUI#getEditorKit * @see javax.swing.plaf.TextUI#getEditorKit
*/ */
@@ -107,16 +105,16 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
public EditorKit getEditorKit(JTextComponent tc) { public EditorKit getEditorKit(JTextComponent tc) {
return DEFAULT_KIT; return DEFAULT_KIT;
} }
/** /**
* Get the InputMap to use for the UI. * Get the InputMap to use for the UI.
* <p> * <p>
* *
* This method is not named <code>getInputMap()</code> because there is * This method is not named <code>getInputMap()</code> because there is a
* a package-private method in <code>BasicTextAreaUI</code> with that name. * package-private method in <code>BasicTextAreaUI</code> with that name. Thus,
* Thus, creating a new method with that name causes certain compilers to * creating a new method with that name causes certain compilers to issue
* issue warnings that you are not actually overriding the original method * warnings that you are not actually overriding the original method (since it
* (since it is package-private). * is package-private).
*/ */
@Override @Override
protected InputMap getRTextAreaInputMap() { protected InputMap getRTextAreaInputMap() {
@@ -132,18 +130,17 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
map.setParent(shared); map.setParent(shared);
return map; return map;
} }
@Override @Override
protected void paintEditorAugmentations(Graphics g) { protected void paintEditorAugmentations(Graphics g) {
super.paintEditorAugmentations(g); super.paintEditorAugmentations(g);
paintMatchedBracket(g); paintMatchedBracket(g);
} }
/** /**
* Paints the "matched bracket", if any. * Paints the "matched bracket", if any.
* *
* @param g * @param g The graphics context.
* The graphics context.
*/ */
protected void paintMatchedBracket(Graphics g) { protected void paintMatchedBracket(Graphics g) {
RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; RSyntaxTextArea rsta = (RSyntaxTextArea) textArea;
@@ -160,7 +157,7 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
} }
} }
} }
protected void paintMatchedBracketImpl(Graphics g, RSyntaxTextArea rsta, Rectangle r) { protected void paintMatchedBracketImpl(Graphics g, RSyntaxTextArea rsta, Rectangle r) {
// We must add "-1" to the height because otherwise we'll paint below // We must add "-1" to the height because otherwise we'll paint below
// the region that gets invalidated. // the region that gets invalidated.
@@ -183,13 +180,12 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
g.drawRect(r.x, r.y, r.width, r.height - 1); g.drawRect(r.x, r.y, r.width, r.height - 1);
} }
} }
/** /**
* Gets called whenever a bound property is changed on this UI's * Gets called whenever a bound property is changed on this UI's
* <code>RSyntaxTextArea</code>. * <code>RSyntaxTextArea</code>.
* *
* @param e * @param e The property change event.
* The property change event.
*/ */
@Override @Override
protected void propertyChange(PropertyChangeEvent e) { protected void propertyChange(PropertyChangeEvent e) {
@@ -204,7 +200,7 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
super.propertyChange(e); super.propertyChange(e);
} }
} }
/** /**
* Updates the view. This should be called when the underlying * Updates the view. This should be called when the underlying
* <code>RSyntaxTextArea</code> changes its syntax editing style. * <code>RSyntaxTextArea</code> changes its syntax editing style.
@@ -212,14 +208,13 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
public void refreshSyntaxHighlighting() { public void refreshSyntaxHighlighting() {
modelChanged(); modelChanged();
} }
/** /**
* Returns the y-coordinate of the specified line. * Returns the y-coordinate of the specified line.
* <p> * <p>
* *
* This method is quicker than using traditional * This method is quicker than using traditional <code>modelToView(int)</code>
* <code>modelToView(int)</code> calls, as the entire bounding box isn't * calls, as the entire bounding box isn't computed.
* computed.
*/ */
@Override @Override
public int yForLine(int line) throws BadLocationException { public int yForLine(int line) throws BadLocationException {
@@ -230,7 +225,7 @@ public class RSyntaxTextAreaUI extends RTextAreaUI {
} }
return -1; return -1;
} }
/** /**
* Returns the y-coordinate of the line containing a specified offset. * Returns the y-coordinate of the line containing a specified offset.
* <p> * <p>
File diff suppressed because it is too large. Load diff
+89 -101
View File
@@ -20,25 +20,24 @@ import java.io.StringReader;
* Gets the plain text version of RTF documents. * Gets the plain text version of RTF documents.
* <p> * <p>
* *
* This is used by <code>RtfTransferable</code> to return the plain text * This is used by <code>RtfTransferable</code> to return the plain text version
* version of the transferable when the receiver does not support RTF. * of the transferable when the receiver does not support RTF.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
final class RtfToText { final class RtfToText {
private Reader r; private Reader r;
private StringBuilder sb; private StringBuilder sb;
private StringBuilder controlWord; private StringBuilder controlWord;
private int blockCount; private int blockCount;
private boolean inControlWord; private boolean inControlWord;
/** /**
* Private constructor. * Private constructor.
* *
* @param r * @param r The reader to read RTF text from.
* The reader to read RTF text from.
*/ */
private RtfToText(Reader r) { private RtfToText(Reader r) {
this.r = r; this.r = r;
@@ -47,15 +46,14 @@ final class RtfToText {
blockCount = 0; blockCount = 0;
inControlWord = false; inControlWord = false;
} }
/** /**
* Converts the RTF text read from this converter's <code>Reader</code> * Converts the RTF text read from this converter's <code>Reader</code> into
* into plain text. It is the caller's responsibility to close the * plain text. It is the caller's responsibility to close the reader after this
* reader after this method is called. * method is called.
* *
* @return The plain text. * @return The plain text.
* @throws IOException * @throws IOException If an IO error occurs.
* If an IO error occurs.
*/ */
private String convert() throws IOException { private String convert() throws IOException {
// Skip over first curly brace as the whole file is in '{' and '}' // Skip over first curly brace as the whole file is in '{' and '}'
@@ -66,76 +64,76 @@ final class RtfToText {
while ((i = r.read()) != -1) { while ((i = r.read()) != -1) {
char ch = (char) i; char ch = (char) i;
switch (ch) { switch (ch) {
case '{': case '{':
if (inControlWord && controlWord.length() == 0) { // "\{" if (inControlWord && controlWord.length() == 0) { // "\{"
sb.append('{'); sb.append('{');
controlWord.setLength(0); controlWord.setLength(0);
inControlWord = false; inControlWord = false;
} else { } else {
blockCount++; blockCount++;
} }
break; break;
case '}': case '}':
if (inControlWord && controlWord.length() == 0) { // "\}" if (inControlWord && controlWord.length() == 0) { // "\}"
sb.append('}'); sb.append('}');
controlWord.setLength(0); controlWord.setLength(0);
inControlWord = false; inControlWord = false;
} else { } else {
blockCount--; blockCount--;
} }
break; break;
case '\\': case '\\':
if (blockCount == 0) { if (blockCount == 0) {
if (inControlWord) { if (inControlWord) {
if (controlWord.length() == 0) { // "\\" if (controlWord.length() == 0) { // "\\"
sb.append('\\'); sb.append('\\');
controlWord.setLength(0); controlWord.setLength(0);
inControlWord = false; inControlWord = false;
} else {
endControlWord();
inControlWord = true;
}
} else { } else {
endControlWord();
inControlWord = true; inControlWord = true;
} }
} else {
inControlWord = true;
} }
break; }
case ' ': break;
if (blockCount == 0) { case ' ':
if (inControlWord) { if (blockCount == 0) {
endControlWord(); if (inControlWord) {
} else { endControlWord();
sb.append(' '); } else {
} sb.append(' ');
} }
break; }
case '\r': break;
case '\n': case '\r':
if (blockCount == 0) { case '\n':
if (inControlWord) { if (blockCount == 0) {
endControlWord(); if (inControlWord) {
} endControlWord();
// Otherwise, ignore
} }
break; // Otherwise, ignore
default: }
if (blockCount == 0) { break;
if (inControlWord) { default:
controlWord.append(ch); if (blockCount == 0) {
} else { if (inControlWord) {
sb.append(ch); controlWord.append(ch);
} } else {
sb.append(ch);
} }
break; }
break;
} }
} }
return sb.toString(); return sb.toString();
} }
/** /**
* Ends a control word. Checks whether it is a common one that affects * Ends a control word. Checks whether it is a common one that affects the plain
* the plain text output (such as "<code>par</code>" or "<code>tab</code>") * text output (such as "<code>par</code>" or "<code>tab</code>") and updates
* and updates the text buffer accordingly. * the text buffer accordingly.
*/ */
private void endControlWord() { private void endControlWord() {
String word = controlWord.toString(); String word = controlWord.toString();
@@ -147,58 +145,50 @@ final class RtfToText {
controlWord.setLength(0); controlWord.setLength(0);
inControlWord = false; inControlWord = false;
} }
/** /**
* Converts the contents of the specified byte array representing * Converts the contents of the specified byte array representing an RTF
* an RTF document into plain text. * document into plain text.
* *
* @param rtf * @param rtf The byte array representing an RTF document.
* The byte array representing an RTF document.
* @return The contents of the RTF document, in plain text. * @return The contents of the RTF document, in plain text.
* @throws IOException * @throws IOException If an IO error occurs.
* If an IO error occurs.
*/ */
public static String getPlainText(byte[] rtf) throws IOException { public static String getPlainText(byte[] rtf) throws IOException {
return getPlainText(new ByteArrayInputStream(rtf)); return getPlainText(new ByteArrayInputStream(rtf));
} }
/** /**
* Converts the contents of the specified RTF file to plain text. * Converts the contents of the specified RTF file to plain text.
* *
* @param file * @param file The RTF file to convert.
* The RTF file to convert.
* @return The contents of the file, in plain text. * @return The contents of the file, in plain text.
* @throws IOException * @throws IOException If an IO error occurs.
* If an IO error occurs.
*/ */
public static String getPlainText(File file) throws IOException { public static String getPlainText(File file) throws IOException {
return getPlainText(new BufferedReader(new FileReader(file))); return getPlainText(new BufferedReader(new FileReader(file)));
} }
/** /**
* Converts the contents of the specified input stream to plain text. * Converts the contents of the specified input stream to plain text. The input
* The input stream will be closed when this method returns. * stream will be closed when this method returns.
* *
* @param in * @param in The input stream to convert. This will be closed when this method
* The input stream to convert. This will be closed when this * returns.
* method returns.
* @return The contents of the stream, in plain text. * @return The contents of the stream, in plain text.
* @throws IOException * @throws IOException If an IO error occurs.
* If an IO error occurs.
*/ */
public static String getPlainText(InputStream in) throws IOException { public static String getPlainText(InputStream in) throws IOException {
return getPlainText(new InputStreamReader(in, "US-ASCII")); return getPlainText(new InputStreamReader(in, "US-ASCII"));
} }
/** /**
* Converts the contents of the specified <code>Reader</code> to plain text. * Converts the contents of the specified <code>Reader</code> to plain text.
* *
* @param r * @param r The <code>Reader</code>. This will be closed when this method
* The <code>Reader</code>. This will be closed when this method * returns.
* returns.
* @return The contents of the <code>Reader</code>, in plain text. * @return The contents of the <code>Reader</code>, in plain text.
* @throws IOException * @throws IOException If an IO error occurs.
* If an IO error occurs.
*/ */
private static String getPlainText(Reader r) throws IOException { private static String getPlainText(Reader r) throws IOException {
try { try {
@@ -208,15 +198,13 @@ final class RtfToText {
r.close(); r.close();
} }
} }
/** /**
* Converts the contents of the specified String to plain text. * Converts the contents of the specified String to plain text.
* *
* @param rtf * @param rtf A string whose contents represent an RTF document.
* A string whose contents represent an RTF document.
* @return The contents of the String, in plain text. * @return The contents of the String, in plain text.
* @throws IOException * @throws IOException If an IO error occurs.
* If an IO error occurs.
*/ */
public static String getPlainText(String rtf) throws IOException { public static String getPlainText(String rtf) throws IOException {
return getPlainText(new StringReader(rtf)); return getPlainText(new StringReader(rtf));
+102 -135
View File
@@ -27,12 +27,10 @@ import org.fife.ui.rtextarea.RTextArea;
* </ul> * </ul>
* *
* The RTF generated isn't really "optimized," but it will do, especially for * The RTF generated isn't really "optimized," but it will do, especially for
* small amounts of text, such as what's common when copy-and-pasting. It * small amounts of text, such as what's common when copy-and-pasting. It tries
* tries to be sufficient for the use case of copying syntax highlighted * to be sufficient for the use case of copying syntax highlighted code:
* code:
* <ul> * <ul>
* <li>It assumes that tokens changing foreground color often is fairly * <li>It assumes that tokens changing foreground color often is fairly common.
* common.
* <li>It assumes that background highlighting is fairly uncommon. * <li>It assumes that background highlighting is fairly uncommon.
* </ul> * </ul>
* *
@@ -40,7 +38,7 @@ import org.fife.ui.rtextarea.RTextArea;
* @version 1.0 * @version 1.0
*/ */
public class RtfGenerator { public class RtfGenerator {
private List<Font> fontList; private List<Font> fontList;
private List<Color> colorList; private List<Color> colorList;
private StringBuilder document; private StringBuilder document;
@@ -53,16 +51,15 @@ public class RtfGenerator {
/** /**
* Java2D assumes a 72 dpi screen resolution, but on Windows the screen * Java2D assumes a 72 dpi screen resolution, but on Windows the screen
* resolution is either 96 dpi or 120 dpi, depending on your font display * resolution is either 96 dpi or 120 dpi, depending on your font display
* settings. This is an attempt to make the RTF generated match the * settings. This is an attempt to make the RTF generated match the size of
* size of what's displayed in the RSyntaxTextArea. * what's displayed in the RSyntaxTextArea.
*/ */
private int screenRes; private int screenRes;
/** /**
* The default font size for RTF. This is point size, in half * The default font size for RTF. This is point size, in half points.
* points.
*/ */
private static final int DEFAULT_FONT_SIZE = 12;// 24; private static final int DEFAULT_FONT_SIZE = 12;// 24;
/** /**
* Constructor. * Constructor.
*/ */
@@ -72,7 +69,7 @@ public class RtfGenerator {
document = new StringBuilder(); document = new StringBuilder();
reset(); reset();
} }
/** /**
* Adds a newline to the RTF document. * Adds a newline to the RTF document.
* *
@@ -83,87 +80,68 @@ public class RtfGenerator {
document.append('\n'); // Just for ease of reading RTF. document.append('\n'); // Just for ease of reading RTF.
lastWasControlWord = false; lastWasControlWord = false;
} }
/** /**
* Appends styled text to the RTF document being generated. * Appends styled text to the RTF document being generated.
* *
* @param text * @param text The text to append.
* The text to append. * @param f The font of the text. If this is <code>null</code>, the default
* @param f * font is used.
* The font of the text. If this is <code>null</code>, the * @param fg The foreground of the text. If this is <code>null</code>, the
* default font is used. * default foreground color is used.
* @param fg * @param bg The background color of the text. If this is <code>null</code>,
* The foreground of the text. If this is <code>null</code>, * the default background color is used.
* the default foreground color is used.
* @param bg
* The background color of the text. If this is
* <code>null</code>, the default background color is used.
* @see #appendNewline() * @see #appendNewline()
*/ */
public void appendToDoc(String text, Font f, Color fg, Color bg) { public void appendToDoc(String text, Font f, Color fg, Color bg) {
appendToDoc(text, f, fg, bg, false); appendToDoc(text, f, fg, bg, false);
} }
/** /**
* Appends styled text to the RTF document being generated. * Appends styled text to the RTF document being generated.
* *
* @param text * @param text The text to append.
* The text to append. * @param f The font of the text. If this is <code>null</code>, the
* @param f * default font is used.
* The font of the text. If this is <code>null</code>, the * @param bg The background color of the text. If this is
* default font is used. * <code>null</code>, the default background color is used.
* @param bg * @param underline Whether the text should be underlined.
* The background color of the text. If this is
* <code>null</code>, the default background color is used.
* @param underline
* Whether the text should be underlined.
* @see #appendNewline() * @see #appendNewline()
*/ */
public void appendToDocNoFG(String text, Font f, Color bg, boolean underline) { public void appendToDocNoFG(String text, Font f, Color bg, boolean underline) {
appendToDoc(text, f, null, bg, underline, false); appendToDoc(text, f, null, bg, underline, false);
} }
/** /**
* Appends styled text to the RTF document being generated. * Appends styled text to the RTF document being generated.
* *
* @param text * @param text The text to append.
* The text to append. * @param f The font of the text. If this is <code>null</code>, the
* @param f * default font is used.
* The font of the text. If this is <code>null</code>, the * @param fg The foreground of the text. If this is <code>null</code>,
* default font is used. * the default foreground color is used.
* @param fg * @param bg The background color of the text. If this is
* The foreground of the text. If this is <code>null</code>, * <code>null</code>, the default background color is used.
* the default foreground color is used. * @param underline Whether the text should be underlined.
* @param bg
* The background color of the text. If this is
* <code>null</code>, the default background color is used.
* @param underline
* Whether the text should be underlined.
* @see #appendNewline() * @see #appendNewline()
*/ */
public void appendToDoc(String text, Font f, Color fg, Color bg, boolean underline) { public void appendToDoc(String text, Font f, Color fg, Color bg, boolean underline) {
appendToDoc(text, f, fg, bg, underline, true); appendToDoc(text, f, fg, bg, underline, true);
} }
/** /**
* Appends styled text to the RTF document being generated. * Appends styled text to the RTF document being generated.
* *
* @param text * @param text The text to append.
* The text to append. * @param f The font of the text. If this is <code>null</code>, the
* @param f * default font is used.
* The font of the text. If this is <code>null</code>, the * @param fg The foreground of the text. If this is <code>null</code>,
* default font is used. * the default foreground color is used.
* @param fg * @param bg The background color of the text. If this is
* The foreground of the text. If this is <code>null</code>, * <code>null</code>, the default background color is used.
* the default foreground color is used. * @param underline Whether the text should be underlined.
* @param bg * @param setFG Whether the foreground specified by <code>fg</code> should
* The background color of the text. If this is * be honored (if it is non-<code>null</code>).
* <code>null</code>, the default background color is used.
* @param underline
* Whether the text should be underlined.
* @param setFG
* Whether the foreground specified by <code>fg</code> should
* be honored (if it is non-<code>null</code>).
* @see #appendNewline() * @see #appendNewline()
*/ */
public void appendToDoc(String text, Font f, Color fg, Color bg, boolean underline, boolean setFG) { public void appendToDoc(String text, Font f, Color fg, Color bg, boolean underline, boolean setFG) {
@@ -248,70 +226,65 @@ public class RtfGenerator {
} }
} }
} }
/** /**
* Appends some text to a buffer, with special care taken for special * Appends some text to a buffer, with special care taken for special characters
* characters as defined by the RTF spec. * as defined by the RTF spec.
* *
* <ul> * <ul>
* <li>All tab characters are replaced with the string * <li>All tab characters are replaced with the string "<code>\tab</code>"
* "<code>\tab</code>"
* <li>'\', '{' and '}' are changed to "\\", "\{" and "\}" * <li>'\', '{' and '}' are changed to "\\", "\{" and "\}"
* </ul> * </ul>
* *
* @param text * @param text The text to append (with tab chars substituted).
* The text to append (with tab chars substituted). * @param sb The buffer to append to.
* @param sb
* The buffer to append to.
*/ */
private void escapeAndAdd(StringBuilder sb, String text) { private void escapeAndAdd(StringBuilder sb, String text) {
int count = text.length(); int count = text.length();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
char ch = text.charAt(i); char ch = text.charAt(i);
switch (ch) { switch (ch) {
case '\t': case '\t':
// Micro-optimization: for syntax highlighting with // Micro-optimization: for syntax highlighting with
// tab indentation, there are often multiple tabs // tab indentation, there are often multiple tabs
// back-to-back at the start of lines, so don't put // back-to-back at the start of lines, so don't put
// spaces between each "\tab". // spaces between each "\tab".
sb.append("\\tab");
while ((++i < count) && text.charAt(i) == '\t') {
sb.append("\\tab"); sb.append("\\tab");
while ((++i < count) && text.charAt(i) == '\t') { }
sb.append("\\tab"); sb.append(' ');
} i--; // We read one too far.
sb.append(' '); break;
i--; // We read one too far. case '\\':
break; case '{':
case '\\': case '}':
case '{': sb.append('\\').append(ch);
case '}': break;
sb.append('\\').append(ch); default:
break; if (ch <= 127) {
default: sb.append(ch);
if (ch <= 127) { } else {
sb.append(ch); sb.append("\\u").append((int) ch);
} else { }
sb.append("\\u").append((int) ch); break;
}
break;
} }
} }
} }
/** /**
* Returns a font point size, adjusted for the current screen resolution. * Returns a font point size, adjusted for the current screen resolution.
* <p> * <p>
* *
* Java2D assumes 72 dpi. On systems with larger dpi (Windows, GTK, etc.), * Java2D assumes 72 dpi. On systems with larger dpi (Windows, GTK, etc.), font
* font rendering will appear too small if we simply return a Java "Font" * rendering will appear too small if we simply return a Java "Font" object's
* object's getSize() value. We need to adjust it for the screen * getSize() value. We need to adjust it for the screen resolution.
* resolution.
* *
* @param pointSize * @param pointSize A Java Font's point size, as returned from
* A Java Font's point size, as returned from * <code>getSize2D()</code>.
* <code>getSize2D()</code>. * @return The font point size, adjusted for the current screen resolution. This
* @return The font point size, adjusted for the current screen resolution. * will allow other applications to render fonts the same size as they
* This will allow other applications to render fonts the same * appear in the Java application.
* size as they appear in the Java application.
*/ */
private int fixFontSize(float pointSize) { private int fixFontSize(float pointSize) {
if (screenRes != 72) { // Java2D assumes 72 dpi if (screenRes != 72) { // Java2D assumes 72 dpi
@@ -319,15 +292,13 @@ public class RtfGenerator {
} }
return (int) pointSize; return (int) pointSize;
} }
/** /**
* Returns the index of the specified item in a list. If the item * Returns the index of the specified item in a list. If the item is not in the
* is not in the list, it is added, and its new index is returned. * list, it is added, and its new index is returned.
* *
* @param list * @param list The list (possibly) containing the item.
* The list (possibly) containing the item. * @param item The item to get the index of.
* @param item
* The item to get the index of.
* @return The index of the item. * @return The index of the item.
*/ */
private static int getColorIndex(List<Color> list, Color item) { private static int getColorIndex(List<Color> list, Color item) {
@@ -338,7 +309,7 @@ public class RtfGenerator {
} }
return pos; return pos;
} }
private String getColorTableRtf() { private String getColorTableRtf() {
// Example: // Example:
// "{\\colortbl ;\\red255\\green0\\blue0;\\red0\\green0\\blue255; }" // "{\\colortbl ;\\red255\\green0\\blue0;\\red0\\green0\\blue255; }"
@@ -353,20 +324,17 @@ public class RtfGenerator {
sb.append("}"); sb.append("}");
return sb.toString(); return sb.toString();
} }
/** /**
* Returns the index of the specified font in a list of fonts. This * Returns the index of the specified font in a list of fonts. This method only
* method only checks for a font by its family name; its attributes such * checks for a font by its family name; its attributes such as bold and italic
* as bold and italic are ignored. * are ignored.
* <p> * <p>
* *
* If the font is not in the list, it is added, and its new index is * If the font is not in the list, it is added, and its new index is returned.
* returned.
* *
* @param list * @param list The list (possibly) containing the font.
* The list (possibly) containing the font. * @param font The font to get the index of.
* @param font
* The font to get the index of.
* @return The index of the font. * @return The index of the font.
*/ */
private static int getFontIndex(List<Font> list, Font font) { private static int getFontIndex(List<Font> list, Font font) {
@@ -380,7 +348,7 @@ public class RtfGenerator {
list.add(font); list.add(font);
return list.size() - 1; return list.size() - 1;
} }
private String getFontTableRtf() { private String getFontTableRtf() {
// Example: // Example:
// "{\\fonttbl{\\f0\\fmodern\\fcharset0 Courier;}}" // "{\\fonttbl{\\f0\\fmodern\\fcharset0 Courier;}}"
@@ -402,10 +370,10 @@ public class RtfGenerator {
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
/** /**
* Returns a good "default" monospaced font to use when Java's logical * Returns a good "default" monospaced font to use when Java's logical font
* font "Monospaced" is found. * "Monospaced" is found.
* *
* @return The monospaced font family to use. * @return The monospaced font family to use.
*/ */
@@ -416,7 +384,7 @@ public class RtfGenerator {
} }
return family; return family;
} }
/** /**
* Returns the RTF document created by this generator. * Returns the RTF document created by this generator.
* *
@@ -440,10 +408,9 @@ public class RtfGenerator {
// System.err.println("*** " + sb.length()); // System.err.println("*** " + sb.length());
return sb.toString(); return sb.toString();
} }
/** /**
* Resets this generator. All document information and content is * Resets this generator. All document information and content is cleared.
* cleared.
*/ */
public void reset() { public void reset() {
fontList.clear(); fontList.clear();
@@ -14,17 +14,16 @@ import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
/** /**
* Object used during copy/paste and DnD operations to represent RTF text. * Object used during copy/paste and DnD operations to represent RTF text. It
* It can return the text being moved as either RTF or plain text. This * can return the text being moved as either RTF or plain text. This class is
* class is basically the same as * basically the same as <code>java.awt.datatransfer.StringSelection</code>,
* <code>java.awt.datatransfer.StringSelection</code>, except that it can also * except that it can also return the text as RTF.
* return the text as RTF.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
class RtfTransferable implements Transferable { class RtfTransferable implements Transferable {
/** /**
* The RTF data, in bytes (the RTF is 7-bit ascii). * The RTF data, in bytes (the RTF is 7-bit ascii).
*/ */
@@ -32,19 +31,19 @@ class RtfTransferable implements Transferable {
/** /**
* The "flavors" the text can be returned as. * The "flavors" the text can be returned as.
*/ */
private static final DataFlavor[] FLAVORS = { new DataFlavor("text/rtf", "RTF"), DataFlavor.stringFlavor, DataFlavor.plainTextFlavor // deprecated private static final DataFlavor[] FLAVORS = { new DataFlavor("text/rtf", "RTF"), DataFlavor.stringFlavor,
DataFlavor.plainTextFlavor // deprecated
}; };
/** /**
* Constructor. * Constructor.
* *
* @param data * @param data The RTF data.
* The RTF data.
*/ */
RtfTransferable(byte[] data) { RtfTransferable(byte[] data) {
this.data = data; this.data = data;
} }
@Override @Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (flavor.equals(FLAVORS[0])) { // RTF if (flavor.equals(FLAVORS[0])) { // RTF
@@ -61,12 +60,12 @@ class RtfTransferable implements Transferable {
throw new UnsupportedFlavorException(flavor); throw new UnsupportedFlavorException(flavor);
} }
} }
@Override @Override
public DataFlavor[] getTransferDataFlavors() { public DataFlavor[] getTransferDataFlavors() {
return FLAVORS.clone(); return FLAVORS.clone();
} }
@Override @Override
public boolean isDataFlavorSupported(DataFlavor flavor) { public boolean isDataFlavorSupported(DataFlavor flavor) {
for (int i = 0; i < FLAVORS.length; i++) { for (int i = 0; i < FLAVORS.length; i++) {
@@ -11,28 +11,28 @@ package org.fife.ui.rsyntaxtextarea;
import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkEvent;
/** /**
* A link generator result that selects a region of text in the text area. * A link generator result that selects a region of text in the text area. This
* This will typically be used by IDE-style applications, to provide support * will typically be used by IDE-style applications, to provide support for
* for "linking" the use of a variable in a document to its declaration. * "linking" the use of a variable in a document to its declaration.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
* @see LinkGenerator * @see LinkGenerator
*/ */
public class SelectRegionLinkGeneratorResult implements LinkGeneratorResult { public class SelectRegionLinkGeneratorResult implements LinkGeneratorResult {
private RSyntaxTextArea textArea; private RSyntaxTextArea textArea;
private int sourceOffset; private int sourceOffset;
private int selStart; private int selStart;
private int selEnd; private int selEnd;
public SelectRegionLinkGeneratorResult(RSyntaxTextArea textArea, int sourceOffset, int selStart, int selEnd) { public SelectRegionLinkGeneratorResult(RSyntaxTextArea textArea, int sourceOffset, int selStart, int selEnd) {
this.textArea = textArea; this.textArea = textArea;
this.sourceOffset = sourceOffset; this.sourceOffset = sourceOffset;
this.selStart = selStart; this.selStart = selStart;
this.selEnd = selEnd; this.selEnd = selEnd;
} }
/** /**
* Selects the text in the text area. * Selects the text in the text area.
*/ */
@@ -41,7 +41,7 @@ public class SelectRegionLinkGeneratorResult implements LinkGeneratorResult {
textArea.select(selStart, selEnd); textArea.select(selStart, selEnd);
return null; return null;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -32,37 +32,29 @@ import org.fife.ui.rtextarea.ChangeableHighlightPainter;
* @version 1.0 * @version 1.0
*/ */
public class SquiggleUnderlineHighlightPainter extends ChangeableHighlightPainter { public class SquiggleUnderlineHighlightPainter extends ChangeableHighlightPainter {
private static final int AMT = 2; private static final int AMT = 2;
/** /**
* Constructor. * Constructor.
* *
* @param color * @param color The color of the squiggle. This cannot be <code>null</code>.
* The color of the squiggle. This cannot be
* <code>null</code>.
*/ */
public SquiggleUnderlineHighlightPainter(Color color) { public SquiggleUnderlineHighlightPainter(Color color) {
super(color); super(color);
setPaint(color); setPaint(color);
} }
/** /**
* Paints a portion of a highlight. * Paints a portion of a highlight.
* *
* @param g * @param g the graphics context
* the graphics context * @param offs0 the starting model offset &gt;= 0
* @param offs0 * @param offs1 the ending model offset &gt;= offs1
* the starting model offset &gt;= 0 * @param bounds the bounding box of the view, which is not necessarily the
* @param offs1 * region to paint.
* the ending model offset &gt;= offs1 * @param c the editor
* @param bounds * @param view View painting for
* the bounding box of the view, which is not
* necessarily the region to paint.
* @param c
* the editor
* @param view
* View painting for
* @return region drawing occurred in * @return region drawing occurred in
*/ */
@Override @Override
@@ -92,14 +84,12 @@ public class SquiggleUnderlineHighlightPainter extends ChangeableHighlightPainte
// Only if exception // Only if exception
return null; return null;
} }
/** /**
* Paints a squiggle underneath text in the specified rectangle. * Paints a squiggle underneath text in the specified rectangle.
* *
* @param g * @param g The graphics context with which to paint.
* The graphics context with which to paint. * @param r The rectangle containing the text.
* @param r
* The rectangle containing the text.
*/ */
protected void paintSquiggle(Graphics g, Rectangle r) { protected void paintSquiggle(Graphics g, Rectangle r) {
int x = r.x; int x = r.x;
@@ -8,8 +8,8 @@ package org.fife.ui.rsyntaxtextarea;
/** /**
* Constants that define the different programming languages understood by * Constants that define the different programming languages understood by
* <code>RSyntaxTextArea</code>. These constants are the values you can pass * <code>RSyntaxTextArea</code>. These constants are the values you can pass to
* to {@link RSyntaxTextArea#setSyntaxEditingStyle(String)} to get syntax * {@link RSyntaxTextArea#setSyntaxEditingStyle(String)} to get syntax
* highlighting. * highlighting.
* <p> * <p>
* *
@@ -25,7 +25,7 @@ package org.fife.ui.rsyntaxtextarea;
* @version 1.0 * @version 1.0
*/ */
public interface SyntaxConstants { public interface SyntaxConstants {
/** /**
* Style meaning don't syntax highlight anything. * Style meaning don't syntax highlight anything.
*/ */
@@ -123,8 +123,8 @@ public interface SyntaxConstants {
*/ */
String SYNTAX_STYLE_JSON = "text/json"; String SYNTAX_STYLE_JSON = "text/json";
/** /**
* Style for highlighting .jshintrc files (JSON with comments, so can be * Style for highlighting .jshintrc files (JSON with comments, so can be used
* used for other times when you want this behavior). * for other times when you want this behavior).
*/ */
String SYNTAX_STYLE_JSON_WITH_COMMENTS = "text/jshintrc"; String SYNTAX_STYLE_JSON_WITH_COMMENTS = "text/jshintrc";
/** /**
+207 -268
View File
@@ -30,14 +30,14 @@ import org.fife.ui.rsyntaxtextarea.folding.FoldManager;
/** /**
* The <code>javax.swing.text.View</code> object used by {@link RSyntaxTextArea} * The <code>javax.swing.text.View</code> object used by {@link RSyntaxTextArea}
* when word wrap is disabled. It implements syntax highlighting for * when word wrap is disabled. It implements syntax highlighting for programming
* programming languages using the colors and font styles specified by the * languages using the colors and font styles specified by the
* <code>RSyntaxTextArea</code>. * <code>RSyntaxTextArea</code>.
* <p> * <p>
* *
* You don't really have to do anything to use this class, as * You don't really have to do anything to use this class, as
* {@link RSyntaxTextAreaUI} automatically sets the text area's view to be * {@link RSyntaxTextAreaUI} automatically sets the text area's view to be an
* an instance of this class if word wrap is disabled. * instance of this class if word wrap is disabled.
* <p> * <p>
* *
* The tokens that specify how to paint the syntax-highlighted text are gleaned * The tokens that specify how to paint the syntax-highlighted text are gleaned
@@ -47,7 +47,7 @@ import org.fife.ui.rsyntaxtextarea.folding.FoldManager;
* @version 0.3 * @version 0.3
*/ */
public class SyntaxView extends View implements TabExpander, TokenOrientedView, RSTAView { public class SyntaxView extends View implements TabExpander, TokenOrientedView, RSTAView {
/** /**
* The default font used by the text area. If this changes we need to * The default font used by the text area. If this changes we need to
* recalculate the longest line. * recalculate the longest line.
@@ -58,9 +58,9 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
*/ */
private FontMetrics metrics; private FontMetrics metrics;
/** /**
* The current longest line. This is used to calculate the preferred width * The current longest line. This is used to calculate the preferred width of
* of the view. Since the calculation is potentially expensive, we try to * the view. Since the calculation is potentially expensive, we try to avoid it
* avoid it by stashing which line is currently the longest. * by stashing which line is currently the longest.
*/ */
private Element longLine; private Element longLine;
private float longLineWidth; private float longLineWidth;
@@ -78,30 +78,28 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
private int clipStart; private int clipStart;
private int clipEnd; private int clipEnd;
/** /**
* Temporary token used when we need to "modify" tokens for rendering * Temporary token used when we need to "modify" tokens for rendering purposes.
* purposes. Since tokens returned from RSyntaxDocuments are treated as * Since tokens returned from RSyntaxDocuments are treated as immutable, we use
* immutable, we use this temporary token to do that work. * this temporary token to do that work.
*/ */
private TokenImpl tempToken; private TokenImpl tempToken;
/** /**
* Constructs a new <code>SyntaxView</code> wrapped around an element. * Constructs a new <code>SyntaxView</code> wrapped around an element.
* *
* @param elem * @param elem The element representing the text to display.
* The element representing the text to display.
*/ */
public SyntaxView(Element elem) { public SyntaxView(Element elem) {
super(elem); super(elem);
tempToken = new TokenImpl(); tempToken = new TokenImpl();
} }
/** /**
* Iterate over the lines represented by the child elements * Iterate over the lines represented by the child elements of the element this
* of the element this view represents, looking for the line * view represents, looking for the line that is the longest. The
* that is the longest. The <em>longLine</em> variable is updated to * <em>longLine</em> variable is updated to represent the longest line
* represent the longest line contained. The <em>font</em> variable * contained. The <em>font</em> variable is updated to indicate the font used to
* is updated to indicate the font used to calculate the * calculate the longest line.
* longest line.
*/ */
void calculateLongestLine() { void calculateLongestLine() {
Component c = getContainer(); Component c = getContainer();
@@ -119,37 +117,30 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
} }
} }
/** /**
* Gives notification from the document that attributes were changed * Gives notification from the document that attributes were changed in a
* in a location that this view is responsible for. * location that this view is responsible for.
* *
* @param changes * @param changes the change information from the associated document
* the change information from the associated document * @param a the current allocation of the view
* @param a * @param f the factory to use to rebuild if the view has children
* the current allocation of the view
* @param f
* the factory to use to rebuild if the view has children
* @see View#changedUpdate * @see View#changedUpdate
*/ */
@Override @Override
public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory f) { public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory f) {
updateDamage(changes, a, f); updateDamage(changes, a, f);
} }
/** /**
* Repaint the given line range. * Repaint the given line range.
* *
* @param line0 * @param line0 The starting line number to repaint. This must be a valid line
* The starting line number to repaint. This must * number in the model.
* be a valid line number in the model. * @param line1 The ending line number to repaint. This must be a valid line
* @param line1 * number in the model.
* The ending line number to repaint. This must * @param a The region allocated for the view to render into.
* be a valid line number in the model. * @param host The component hosting the view (used to call repaint).
* @param a
* The region allocated for the view to render into.
* @param host
* The component hosting the view (used to call repaint).
*/ */
protected void damageLineRange(int line0, int line1, Shape a, Component host) { protected void damageLineRange(int line0, int line1, Shape a, Component host) {
if (a != null) { if (a != null) {
@@ -163,23 +154,17 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
} }
} }
/** /**
* Draws the passed-in text using syntax highlighting for the current * Draws the passed-in text using syntax highlighting for the current language.
* language. It is assumed that the entire line is either not in a * It is assumed that the entire line is either not in a selected region, or
* selected region, or painting with a selection-foreground color is turned * painting with a selection-foreground color is turned off.
* off.
* *
* @param painter * @param painter The painter to render the tokens.
* The painter to render the tokens. * @param token The list of tokens to draw.
* @param token * @param g The graphics context in which to draw.
* The list of tokens to draw. * @param x The x-coordinate at which to draw.
* @param g * @param y The y-coordinate at which to draw.
* The graphics context in which to draw.
* @param x
* The x-coordinate at which to draw.
* @param y
* The y-coordinate at which to draw.
* @return The x-coordinate representing the end of the painted text. * @return The x-coordinate representing the end of the painted text.
*/ */
private float drawLine(TokenPainter painter, Token token, Graphics2D g, float x, float y, int line) { private float drawLine(TokenPainter painter, Token token, Graphics2D g, float x, float y, int line) {
@@ -199,29 +184,23 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
// Return the x-coordinate at the end of the painted text. // Return the x-coordinate at the end of the painted text.
return nextX; return nextX;
} }
/** /**
* Draws the passed-in text using syntax highlighting for the current * Draws the passed-in text using syntax highlighting for the current language.
* language. Tokens are checked for being in a selected region, and are * Tokens are checked for being in a selected region, and are rendered
* rendered appropriately if they are. * appropriately if they are.
* *
* @param painter * @param painter The painter to render the tokens.
* The painter to render the tokens. * @param token The list of tokens to draw.
* @param token * @param g The graphics context in which to draw.
* The list of tokens to draw. * @param x The x-coordinate at which to draw.
* @param g * @param y The y-coordinate at which to draw.
* The graphics context in which to draw. * @param selStart The start of the selection.
* @param x * @param selEnd The end of the selection.
* The x-coordinate at which to draw.
* @param y
* The y-coordinate at which to draw.
* @param selStart
* The start of the selection.
* @param selEnd
* The end of the selection.
* @return The x-coordinate representing the end of the painted text. * @return The x-coordinate representing the end of the painted text.
*/ */
private float drawLineWithSelection(TokenPainter painter, Token token, Graphics2D g, float x, float y, int selStart, int selEnd) { private float drawLineWithSelection(TokenPainter painter, Token token, Graphics2D g, float x, float y, int selStart,
int selEnd) {
float nextX = x; // The x-value at the end of our text. float nextX = x; // The x-value at the end of our text.
boolean useSTC = host.getUseSelectedTextColor(); boolean useSTC = host.getUseSelectedTextColor();
while (token != null && token.isPaintable() && nextX < clipEnd) { while (token != null && token.isPaintable() && nextX < clipEnd) {
@@ -281,90 +260,81 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
// Return the x-coordinate at the end of the painted text. // Return the x-coordinate at the end of the painted text.
return nextX; return nextX;
} }
/** /**
* Calculates the width of the line represented by the given element. * Calculates the width of the line represented by the given element.
* *
* @param line * @param line The line for which to get the length.
* The line for which to get the length. * @param lineNumber The line number of the specified line in the document.
* @param lineNumber
* The line number of the specified line in the document.
* @return The width of the line. * @return The width of the line.
*/ */
private float getLineWidth(int lineNumber) { private float getLineWidth(int lineNumber) {
Token tokenList = ((RSyntaxDocument) getDocument()).getTokenListForLine(lineNumber); Token tokenList = ((RSyntaxDocument) getDocument()).getTokenListForLine(lineNumber);
return RSyntaxUtilities.getTokenListWidth(tokenList, (RSyntaxTextArea) getContainer(), this); return RSyntaxUtilities.getTokenListWidth(tokenList, (RSyntaxTextArea) getContainer(), this);
} }
/** /**
* Provides a way to determine the next visually represented model * Provides a way to determine the next visually represented model location that
* location that one might place a caret. Some views may not be visible, * one might place a caret. Some views may not be visible, they might not be in
* they might not be in the same order found in the model, or they just * the same order found in the model, or they just might not allow access to
* might not allow access to some of the locations in the model. * some of the locations in the model.
* *
* @param pos * @param pos the position to convert &gt;= 0
* the position to convert &gt;= 0 * @param a the allocated region to render into
* @param a * @param direction the direction from the current position that can be thought
* the allocated region to render into * of as the arrow keys typically found on a keyboard. This may
* @param direction * be SwingConstants.WEST, SwingConstants.EAST,
* the direction from the current position that can * SwingConstants.NORTH, or SwingConstants.SOUTH.
* be thought of as the arrow keys typically found on a keyboard. * @return the location within the model that best represents the next location
* This may be SwingConstants.WEST, SwingConstants.EAST, * visual position.
* SwingConstants.NORTH, or SwingConstants.SOUTH.
* @return the location within the model that best represents the next
* location visual position.
* @exception BadLocationException * @exception BadLocationException
* @exception IllegalArgumentException * @exception IllegalArgumentException for an invalid direction
* for an invalid direction
*/ */
@Override @Override
public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet) public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet)
throws BadLocationException { throws BadLocationException {
return RSyntaxUtilities.getNextVisualPositionFrom(pos, b, a, direction, biasRet, this); return RSyntaxUtilities.getNextVisualPositionFrom(pos, b, a, direction, biasRet, this);
} }
/** /**
* Determines the preferred span for this view along an * Determines the preferred span for this view along an axis.
* axis.
* *
* @param axis * @param axis may be either View.X_AXIS or View.Y_AXIS
* may be either View.X_AXIS or View.Y_AXIS * @return the span the view would like to be rendered into &gt;= 0. Typically
* @return the span the view would like to be rendered into &gt;= 0. * the view is told to render into the span that is returned, although
* Typically the view is told to render into the span * there is no guarantee. The parent may choose to resize or break the
* that is returned, although there is no guarantee. * view.
* The parent may choose to resize or break the view. * @exception IllegalArgumentException for an invalid axis
* @exception IllegalArgumentException
* for an invalid axis
*/ */
@Override @Override
public float getPreferredSpan(int axis) { public float getPreferredSpan(int axis) {
updateMetrics(); updateMetrics();
switch (axis) { switch (axis) {
case View.X_AXIS: case View.X_AXIS:
float span = longLineWidth + getRhsCorrection(); // fudge factor float span = longLineWidth + getRhsCorrection(); // fudge factor
if (host.getEOLMarkersVisible()) { if (host.getEOLMarkersVisible()) {
span += metrics.charWidth('\u00B6'); span += metrics.charWidth('\u00B6');
} }
return span; return span;
case View.Y_AXIS: case View.Y_AXIS:
// We update lineHeight here as when this method is first // We update lineHeight here as when this method is first
// called, lineHeight isn't initialized. If we don't do it // called, lineHeight isn't initialized. If we don't do it
// here, we get no vertical scrollbar (as lineHeight==0). // here, we get no vertical scrollbar (as lineHeight==0).
lineHeight = host != null ? host.getLineHeight() : lineHeight; lineHeight = host != null ? host.getLineHeight() : lineHeight;
// return getElement().getElementCount() * lineHeight; // return getElement().getElementCount() * lineHeight;
int visibleLineCount = getElement().getElementCount(); int visibleLineCount = getElement().getElementCount();
if (host.isCodeFoldingEnabled()) { if (host.isCodeFoldingEnabled()) {
visibleLineCount -= host.getFoldManager().getHiddenLineCount(); visibleLineCount -= host.getFoldManager().getHiddenLineCount();
} }
return visibleLineCount * (float) lineHeight; return visibleLineCount * (float) lineHeight;
default: default:
throw new IllegalArgumentException("Invalid axis: " + axis); throw new IllegalArgumentException("Invalid axis: " + axis);
} }
} }
/** /**
* Workaround for JTextComponents allowing the caret to be rendered * Workaround for JTextComponents allowing the caret to be rendered entirely
* entirely off-screen if the entire "previous" character fit entirely. * off-screen if the entire "previous" character fit entirely.
* *
* @return The amount of space to add to the x-axis preferred span. * @return The amount of space to add to the x-axis preferred span.
*/ */
@@ -375,7 +345,7 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
return rhsCorrection; return rhsCorrection;
} }
/** /**
* Returns the tab size set for the document, defaulting to 5. * Returns the tab size set for the document, defaulting to 5.
* *
@@ -386,19 +356,17 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
int size = (i != null) ? i.intValue() : 5; int size = (i != null) ? i.intValue() : 5;
return size; return size;
} }
/** /**
* Returns a token list for the <i>physical</i> line above the physical * Returns a token list for the <i>physical</i> line above the physical line
* line containing the specified offset into the document. Note that for * containing the specified offset into the document. Note that for this plain
* this plain (non-wrapped) view, this is simply the token list for the * (non-wrapped) view, this is simply the token list for the logical line above
* logical line above the line containing <code>offset</code>, since lines * the line containing <code>offset</code>, since lines are not wrapped.
* are not wrapped.
* *
* @param offset * @param offset The offset in question.
* The offset in question. * @return A token list for the physical (and in this view, logical) line before
* @return A token list for the physical (and in this view, logical) line * this one. If <code>offset</code> is in the first line in the
* before this one. If <code>offset</code> is in the first line in * document, <code>null</code> is returned.
* the document, <code>null</code> is returned.
*/ */
@Override @Override
public Token getTokenListForPhysicalLineAbove(int offset) { public Token getTokenListForPhysicalLineAbove(int offset) {
@@ -422,19 +390,17 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
// return document.getTokenListForLine(line); // return document.getTokenListForLine(line);
return null; return null;
} }
/** /**
* Returns a token list for the <i>physical</i> line below the physical * Returns a token list for the <i>physical</i> line below the physical line
* line containing the specified offset into the document. Note that for * containing the specified offset into the document. Note that for this plain
* this plain (non-wrapped) view, this is simply the token list for the * (non-wrapped) view, this is simply the token list for the logical line below
* logical line below the line containing <code>offset</code>, since lines * the line containing <code>offset</code>, since lines are not wrapped.
* are not wrapped.
* *
* @param offset * @param offset The offset in question.
* The offset in question. * @return A token list for the physical (and in this view, logical) line after
* @return A token list for the physical (and in this view, logical) line * this one. If <code>offset</code> is in the last physical line in the
* after this one. If <code>offset</code> is in the last physical * document, <code>null</code> is returned.
* line in the document, <code>null</code> is returned.
*/ */
@Override @Override
public Token getTokenListForPhysicalLineBelow(int offset) { public Token getTokenListForPhysicalLineBelow(int offset) {
@@ -459,31 +425,26 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
// return document.getTokenListForLine(line+1); // return document.getTokenListForLine(line+1);
return null; return null;
} }
/** /**
* Gives notification that something was inserted into the document * Gives notification that something was inserted into the document in a
* in a location that this view is responsible for. * location that this view is responsible for.
* *
* @param changes * @param changes The change information from the associated document.
* The change information from the associated document. * @param a The current allocation of the view.
* @param a * @param f The factory to use to rebuild if the view has children.
* The current allocation of the view.
* @param f
* The factory to use to rebuild if the view has children.
*/ */
@Override @Override
public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f) { public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f) {
updateDamage(changes, a, f); updateDamage(changes, a, f);
} }
/** /**
* Determine the rectangle that represents the given line. * Determine the rectangle that represents the given line.
* *
* @param a * @param a The region allocated for the view to render into
* The region allocated for the view to render into * @param line The line number to find the region of. This must be a valid line
* @param line * number in the model.
* The line number to find the region of. This must
* be a valid line number in the model.
*/ */
protected Rectangle lineToRect(Shape a, int line) { protected Rectangle lineToRect(Shape a, int line) {
Rectangle r = null; Rectangle r = null;
@@ -503,19 +464,16 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
return r; return r;
} }
/** /**
* Provides a mapping from the document model coordinate space * Provides a mapping from the document model coordinate space to the coordinate
* to the coordinate space of the view mapped to it. * space of the view mapped to it.
* *
* @param pos * @param pos the position to convert &gt;= 0
* the position to convert &gt;= 0 * @param a the allocated region to render into
* @param a
* the allocated region to render into
* @return the bounding box of the given position * @return the bounding box of the given position
* @exception BadLocationException * @exception BadLocationException if the given position does not represent a
* if the given position does not * valid location in the associated document
* represent a valid location in the associated document
* @see View#modelToView * @see View#modelToView
*/ */
@Override @Override
@@ -535,48 +493,43 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
lineArea = tokenList.listOffsetToView((RSyntaxTextArea) getContainer(), this, pos, tabBase, lineArea); lineArea = tokenList.listOffsetToView((RSyntaxTextArea) getContainer(), this, pos, tabBase, lineArea);
return lineArea; return lineArea;
} }
/** /**
* Provides a mapping, for a given region, from the document model * Provides a mapping, for a given region, from the document model coordinate
* coordinate space to the view coordinate space. The specified region is * space to the view coordinate space. The specified region is created as a
* created as a union of the first and last character positions. * union of the first and last character positions.
* <p> * <p>
* *
* This is implemented to subtract the width of the second character, as * This is implemented to subtract the width of the second character, as this
* this view's <code>modelToView</code> actually returns the width of the * view's <code>modelToView</code> actually returns the width of the character
* character instead of "1" or "0" like the View implementations in * instead of "1" or "0" like the View implementations in
* <code>javax.swing.text</code>. Thus, if we don't override this method, * <code>javax.swing.text</code>. Thus, if we don't override this method, the
* the <code>View</code> implementation will return one character's width * <code>View</code> implementation will return one character's width too much
* too much for its consumers (implementations of * for its consumers (implementations of
* <code>javax.swing.text.Highlighter</code>). * <code>javax.swing.text.Highlighter</code>).
* *
* @param p0 * @param p0 the position of the first character (&gt;=0)
* the position of the first character (&gt;=0) * @param b0 The bias of the first character position, toward the previous
* @param b0 * character or the next character represented by the offset, in case
* The bias of the first character position, toward the previous * the position is a boundary of two views; <code>b0</code> will have
* character or the next character represented by the offset, in * one of these values:
* case the position is a boundary of two views; <code>b0</code> * <ul>
* will have one of these values: * <li><code>Position.Bias.Forward</code>
* <ul> * <li><code>Position.Bias.Backward</code>
* <li><code>Position.Bias.Forward</code> * </ul>
* <li><code>Position.Bias.Backward</code> * @param p1 the position of the last character (&gt;=0)
* </ul> * @param b1 the bias for the second character position, defined one of the
* @param p1 * legal values shown above
* the position of the last character (&gt;=0) * @param a the area of the view, which encompasses the requested region
* @param b1 * @return the bounding box which is a union of the region specified by the
* the bias for the second character position, defined * first and last character positions
* one of the legal values shown above * @exception BadLocationException if the given position does not represent
* @param a * a valid location in the associated
* the area of the view, which encompasses the requested region * document
* @return the bounding box which is a union of the region specified * @exception IllegalArgumentException if <code>b0</code> or <code>b1</code> are
* by the first and last character positions * not one of the legal
* @exception BadLocationException * <code>Position.Bias</code> values listed
* if the given position does * above
* not represent a valid location in the associated document
* @exception IllegalArgumentException
* if <code>b0</code> or
* <code>b1</code> are not one of the
* legal <code>Position.Bias</code> values listed above
* @see View#viewToModel * @see View#viewToModel
*/ */
@Override @Override
@@ -618,17 +571,15 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
return r0; return r0;
} }
/** /**
* Returns the next tab stop position after a given reference position. * Returns the next tab stop position after a given reference position. This
* This implementation does not support things like centering so it * implementation does not support things like centering so it ignores the
* ignores the tabOffset argument. * tabOffset argument.
* *
* @param x * @param x the current position &gt;= 0
* the current position &gt;= 0 * @param tabOffset the position within the text stream that the tab occurred at
* @param tabOffset * &gt;= 0.
* the position within the text stream
* that the tab occurred at &gt;= 0.
* @return the tab stop, measured in points &gt;= 0 * @return the tab stop, measured in points &gt;= 0
*/ */
@Override @Override
@@ -639,15 +590,13 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
int ntabs = (((int) x) - tabBase) / tabSize; int ntabs = (((int) x) - tabBase) / tabSize;
return tabBase + ((ntabs + 1f) * tabSize); return tabBase + ((ntabs + 1f) * tabSize);
} }
/** /**
* Actually paints the text area. Only lines that have been damaged are * Actually paints the text area. Only lines that have been damaged are
* repainted. * repainted.
* *
* @param g * @param g The graphics context with which to paint.
* The graphics context with which to paint. * @param a The allocated region in which to render.
* @param a
* The allocated region in which to render.
*/ */
@Override @Override
public void paint(Graphics g, Shape a) { public void paint(Graphics g, Shape a) {
@@ -726,15 +675,13 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
// System.out.println("SyntaxView: lines painted=" + count); // System.out.println("SyntaxView: lines painted=" + count);
} }
/** /**
* If the passed-in line is longer than the current longest line, then * If the passed-in line is longer than the current longest line, then the
* the longest line is updated. * longest line is updated.
* *
* @param line * @param line The line to test against the current longest.
* The line to test against the current longest. * @param lineNumber The line number of the passed-in line.
* @param lineNumber
* The line number of the passed-in line.
* @return <code>true</code> iff the current longest line was updated. * @return <code>true</code> iff the current longest line was updated.
*/ */
private boolean possiblyUpdateLongLine(Element line, int lineNumber) { private boolean possiblyUpdateLongLine(Element line, int lineNumber) {
@@ -746,36 +693,31 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
return false; return false;
} }
/** /**
* Gives notification that something was removed from the document * Gives notification that something was removed from the document in a location
* in a location that this view is responsible for. * that this view is responsible for.
* *
* @param changes * @param changes the change information from the associated document
* the change information from the associated document * @param a the current allocation of the view
* @param a * @param f the factory to use to rebuild if the view has children
* the current allocation of the view
* @param f
* the factory to use to rebuild if the view has children
*/ */
@Override @Override
public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) { public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) {
updateDamage(changes, a, f); updateDamage(changes, a, f);
} }
@Override @Override
public void setSize(float width, float height) { public void setSize(float width, float height) {
super.setSize(width, height); super.setSize(width, height);
updateMetrics(); updateMetrics();
} }
/** /**
* Repaint the region of change covered by the given document * Repaint the region of change covered by the given document event. Damages the
* event. Damages the line that begins the range to cover * line that begins the range to cover the case when the insert/remove is only
* the case when the insert/remove is only on one line. * on one line. If lines are added or removed, damages the whole view. The
* If lines are added or removed, damages the whole * longest line is checked to see if it has changed.
* view. The longest line is checked to see if it has
* changed.
*/ */
protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f) { protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f) {
Component host = getContainer(); Component host = getContainer();
@@ -841,7 +783,7 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
} }
} }
/** /**
* Checks to see if the font metrics and longest line are up-to-date. * Checks to see if the font metrics and longest line are up-to-date.
*/ */
@@ -854,19 +796,16 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
calculateLongestLine(); calculateLongestLine();
} }
} }
/** /**
* Provides a mapping from the view coordinate space to the logical * Provides a mapping from the view coordinate space to the logical coordinate
* coordinate space of the model. * space of the model.
* *
* @param fx * @param fx the X coordinate &gt;= 0
* the X coordinate &gt;= 0 * @param fy the Y coordinate &gt;= 0
* @param fy * @param a the allocated region to render into
* the Y coordinate &gt;= 0 * @return the location within the model that best represents the given point in
* @param a * the view &gt;= 0
* the allocated region to render into
* @return the location within the model that best represents the
* given point in the view &gt;= 0
*/ */
@Override @Override
public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) { public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) {
@@ -918,7 +857,7 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
} // End of else. } // End of else.
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -941,7 +880,7 @@ public class SyntaxView extends View implements TabExpander, TokenOrientedView,
} }
return -1; return -1;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -28,8 +28,8 @@ import org.fife.io.UnicodeWriter;
import org.fife.ui.rtextarea.RTextAreaEditorKit; import org.fife.ui.rtextarea.RTextAreaEditorKit;
/** /**
* An extension of {@link org.fife.ui.rsyntaxtextarea.RSyntaxTextArea} * An extension of {@link org.fife.ui.rsyntaxtextarea.RSyntaxTextArea} that adds
* that adds information about the file being edited, such as: * information about the file being edited, such as:
* *
* <ul> * <ul>
* <li>Its name and location. * <li>Its name and location.
@@ -43,10 +43,10 @@ import org.fife.ui.rtextarea.RTextAreaEditorKit;
* Loading and saving is also built into the editor. * Loading and saving is also built into the editor.
* <p> * <p>
* *
* When saving UTF-8 files, whether or not a BOM is written is controlled by * When saving UTF-8 files, whether or not a BOM is written is controlled by the
* the {@link UnicodeWriter} class. * {@link UnicodeWriter} class. Use
* Use {@link UnicodeWriter#setWriteUtf8BOM(boolean)} to toggle writing BOMs * {@link UnicodeWriter#setWriteUtf8BOM(boolean)} to toggle writing BOMs for
* for UTF-8 files. * UTF-8 files.
* <p> * <p>
* *
* Both local and remote files (e.g. ftp) are supported. See the * Both local and remote files (e.g. ftp) are supported. See the
@@ -57,11 +57,11 @@ import org.fife.ui.rtextarea.RTextAreaEditorKit;
* @see FileLocation * @see FileLocation
*/ */
public class TextEditorPane extends RSyntaxTextArea implements DocumentListener { public class TextEditorPane extends RSyntaxTextArea implements DocumentListener {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Property change event fired when the file path this text area references * Property change event fired when the file path this text area references is
* is updated. * updated.
* *
* @see #load(FileLocation, String) * @see #load(FileLocation, String)
* @see #saveAs(FileLocation) * @see #saveAs(FileLocation)
@@ -103,9 +103,8 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
*/ */
private boolean dirty; private boolean dirty;
/** /**
* The last time this file was modified on disk, for local files. * The last time this file was modified on disk, for local files. For remote
* For remote files, this value should always be * files, this value should always be {@link #LAST_MODIFIED_UNKNOWN}.
* {@link #LAST_MODIFIED_UNKNOWN}.
*/ */
private long lastSaveOrLoadTime; private long lastSaveOrLoadTime;
/** /**
@@ -116,34 +115,31 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
* The default name given to files if none is specified in a constructor. * The default name given to files if none is specified in a constructor.
*/ */
private static final String DEFAULT_FILE_NAME = "Untitled.txt"; private static final String DEFAULT_FILE_NAME = "Untitled.txt";
/** /**
* Constructor. The file will be given a default name. * Constructor. The file will be given a default name.
*/ */
public TextEditorPane() { public TextEditorPane() {
this(INSERT_MODE); this(INSERT_MODE);
} }
/** /**
* Constructor. The file will be given a default name. * Constructor. The file will be given a default name.
* *
* @param textMode * @param textMode Either <code>INSERT_MODE</code> or
* Either <code>INSERT_MODE</code> or * <code>OVERWRITE_MODE</code>.
* <code>OVERWRITE_MODE</code>.
*/ */
public TextEditorPane(int textMode) { public TextEditorPane(int textMode) {
this(textMode, false); this(textMode, false);
} }
/** /**
* Creates a new <code>TextEditorPane</code>. The file will be given * Creates a new <code>TextEditorPane</code>. The file will be given a default
* a default name. * name.
* *
* @param textMode * @param textMode Either <code>INSERT_MODE</code> or
* Either <code>INSERT_MODE</code> or * <code>OVERWRITE_MODE</code>.
* <code>OVERWRITE_MODE</code>. * @param wordWrapEnabled Whether or not to use word wrap in this pane.
* @param wordWrapEnabled
* Whether or not to use word wrap in this pane.
*/ */
public TextEditorPane(int textMode, boolean wordWrapEnabled) { public TextEditorPane(int textMode, boolean wordWrapEnabled) {
super(textMode); super(textMode);
@@ -154,69 +150,58 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
ioe.printStackTrace(); ioe.printStackTrace();
} }
} }
/** /**
* Creates a new <code>TextEditorPane</code>. * Creates a new <code>TextEditorPane</code>.
* *
* @param textMode * @param textMode Either <code>INSERT_MODE</code> or
* Either <code>INSERT_MODE</code> or * <code>OVERWRITE_MODE</code>.
* <code>OVERWRITE_MODE</code>. * @param wordWrapEnabled Whether or not to use word wrap in this pane.
* @param wordWrapEnabled * @param loc The location of the text file being edited. If this
* Whether or not to use word wrap in this pane. * value is <code>null</code>, a file named
* @param loc * "Untitled.txt" in the current directory is used.
* The location of the text file being edited. If this value * @throws IOException If an IO error occurs reading the file at
* is <code>null</code>, a file named "Untitled.txt" in the * <code>loc</code>. This of course won't happen if
* current * <code>loc</code> is <code>null</code>.
* directory is used.
* @throws IOException
* If an IO error occurs reading the file at
* <code>loc</code>. This of course won't happen if
* <code>loc</code> is <code>null</code>.
*/ */
public TextEditorPane(int textMode, boolean wordWrapEnabled, FileLocation loc) throws IOException { public TextEditorPane(int textMode, boolean wordWrapEnabled, FileLocation loc) throws IOException {
this(textMode, wordWrapEnabled, loc, null); this(textMode, wordWrapEnabled, loc, null);
} }
/** /**
* Creates a new <code>TextEditorPane</code>. * Creates a new <code>TextEditorPane</code>.
* *
* @param textMode * @param textMode Either <code>INSERT_MODE</code> or
* Either <code>INSERT_MODE</code> or * <code>OVERWRITE_MODE</code>.
* <code>OVERWRITE_MODE</code>. * @param wordWrapEnabled Whether or not to use word wrap in this pane.
* @param wordWrapEnabled * @param loc The location of the text file being edited. If this
* Whether or not to use word wrap in this pane. * value is <code>null</code>, a file named
* @param loc * "Untitled.txt" in the current directory is used. This
* The location of the text file being edited. If this value * file is displayed as empty even if it actually exists.
* is <code>null</code>, a file named "Untitled.txt" in the * @param defaultEnc The default encoding to use when opening the file, if
* current * the file is not Unicode. If this value is
* directory is used. This file is displayed as empty even if it * <code>null</code>, a system default value is used.
* actually exists. * @throws IOException If an IO error occurs reading the file at
* @param defaultEnc * <code>loc</code>. This of course won't happen if
* The default encoding to use when opening the file, * <code>loc</code> is <code>null</code>.
* if the file is not Unicode. If this value is
* <code>null</code>,
* a system default value is used.
* @throws IOException
* If an IO error occurs reading the file at
* <code>loc</code>. This of course won't happen if
* <code>loc</code> is <code>null</code>.
*/ */
public TextEditorPane(int textMode, boolean wordWrapEnabled, FileLocation loc, String defaultEnc) throws IOException { public TextEditorPane(int textMode, boolean wordWrapEnabled, FileLocation loc, String defaultEnc)
throws IOException {
super(textMode); super(textMode);
setLineWrap(wordWrapEnabled); setLineWrap(wordWrapEnabled);
init(loc, defaultEnc); init(loc, defaultEnc);
} }
/** /**
* Callback for when styles in the current document change. * Callback for when styles in the current document change. This method is never
* This method is never called. * called.
* *
* @param e * @param e The document event.
* The document event.
*/ */
@Override @Override
public void changedUpdate(DocumentEvent e) {} public void changedUpdate(DocumentEvent e) {
}
/** /**
* Returns the default encoding for this operating system. * Returns the default encoding for this operating system.
* *
@@ -239,7 +224,7 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
} }
return encoding; return encoding;
} }
/** /**
* Returns the encoding to use when reading or writing this file. * Returns the encoding to use when reading or writing this file.
* *
@@ -249,7 +234,7 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
public String getEncoding() { public String getEncoding() {
return charSet; return charSet;
} }
/** /**
* Returns the full path to this document. * Returns the full path to this document.
* *
@@ -258,7 +243,7 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
public String getFileFullPath() { public String getFileFullPath() {
return loc == null ? null : loc.getFileFullPath(); return loc == null ? null : loc.getFileFullPath();
} }
/** /**
* Returns the file name of this document. * Returns the file name of this document.
* *
@@ -267,61 +252,58 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
public String getFileName() { public String getFileName() {
return loc == null ? null : loc.getFileName(); return loc == null ? null : loc.getFileName();
} }
/** /**
* Returns the timestamp for when this file was last loaded or saved * Returns the timestamp for when this file was last loaded or saved <em>by this
* <em>by this editor pane</em>. If the file has been modified on disk by * editor pane</em>. If the file has been modified on disk by another process
* another process after it was loaded into this editor pane, this method * after it was loaded into this editor pane, this method will not return the
* will not return the actual file's last modified time. * actual file's last modified time.
* <p> * <p>
* *
* For remote files, this method will always return * For remote files, this method will always return
* {@link #LAST_MODIFIED_UNKNOWN}. * {@link #LAST_MODIFIED_UNKNOWN}.
* *
* @return The timestamp when this file was last loaded or saved by this * @return The timestamp when this file was last loaded or saved by this editor
* editor pane, if it is a local file, or * pane, if it is a local file, or {@link #LAST_MODIFIED_UNKNOWN} if it
* {@link #LAST_MODIFIED_UNKNOWN} if it is a remote file. * is a remote file.
* @see #isModifiedOutsideEditor() * @see #isModifiedOutsideEditor()
*/ */
public long getLastSaveOrLoadTime() { public long getLastSaveOrLoadTime() {
return lastSaveOrLoadTime; return lastSaveOrLoadTime;
} }
/** /**
* Returns the line separator used when writing this file (e.g. * Returns the line separator used when writing this file (e.g.
* "<code>\n</code>", "<code>\r\n</code>", or "<code>\r</code>"). * "<code>\n</code>", "<code>\r\n</code>", or "<code>\r</code>").
* <p> * <p>
* *
* Note that this value is an <code>Object</code> and not a * Note that this value is an <code>Object</code> and not a <code>String</code>
* <code>String</code> as that is the way the {@link Document} interface * as that is the way the {@link Document} interface defines its property
* defines its property values. If you always use * values. If you always use {@link #setLineSeparator(String)} to modify this
* {@link #setLineSeparator(String)} to modify this value, then the value * value, then the value returned from this method will always be a
* returned from this method will always be a <code>String</code>. * <code>String</code>.
* *
* @return The line separator. If this value is <code>null</code>, then * @return The line separator. If this value is <code>null</code>, then the
* the system default line separator is used (usually the value * system default line separator is used (usually the value of
* of <code>System.getProperty("line.separator")</code>). * <code>System.getProperty("line.separator")</code>).
* @see #setLineSeparator(String) * @see #setLineSeparator(String)
* @see #setLineSeparator(String, boolean) * @see #setLineSeparator(String, boolean)
*/ */
public Object getLineSeparator() { public Object getLineSeparator() {
return getDocument().getProperty(RTextAreaEditorKit.EndOfLineStringProperty); return getDocument().getProperty(RTextAreaEditorKit.EndOfLineStringProperty);
} }
/** /**
* Initializes this editor with the specified file location. * Initializes this editor with the specified file location.
* *
* @param loc * @param loc The file location. If this is <code>null</code>, a default
* The file location. If this is <code>null</code>, a default * location is used and an empty file is displayed.
* location is used and an empty file is displayed. * @param defaultEnc The default encoding to use when opening the file, if the
* @param defaultEnc * file is not Unicode. If this value is <code>null</code>, a
* The default encoding to use when opening the file, * system default value is used.
* if the file is not Unicode. If this value is * @throws IOException If an IO error occurs reading from <code>loc</code>. If
* <code>null</code>, * <code>loc</code> is <code>null</code>, this cannot
* a system default value is used. * happen.
* @throws IOException
* If an IO error occurs reading from <code>loc</code>.
* If <code>loc</code> is <code>null</code>, this cannot happen.
*/ */
private void init(FileLocation loc, String defaultEnc) throws IOException { private void init(FileLocation loc, String defaultEnc) throws IOException {
if (loc == null) { if (loc == null) {
@@ -347,12 +329,11 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
} }
setDirty(false); setDirty(false);
} }
/** /**
* Callback for when text is inserted into the document. * Callback for when text is inserted into the document.
* *
* @param e * @param e Information on the insertion.
* Information on the insertion.
*/ */
@Override @Override
public void insertUpdate(DocumentEvent e) { public void insertUpdate(DocumentEvent e) {
@@ -360,7 +341,7 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
setDirty(true); setDirty(true);
} }
} }
/** /**
* Returns whether or not the text in this editor has unsaved changes. * Returns whether or not the text in this editor has unsaved changes.
* *
@@ -370,7 +351,7 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
public boolean isDirty() { public boolean isDirty() {
return dirty; return dirty;
} }
/** /**
* Returns whether this file is a local file. * Returns whether this file is a local file.
* *
@@ -379,7 +360,7 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
public boolean isLocal() { public boolean isLocal() {
return loc.isLocal(); return loc.isLocal();
} }
/** /**
* Returns whether this is a local file that already exists. * Returns whether this is a local file that already exists.
* *
@@ -388,25 +369,24 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
public boolean isLocalAndExists() { public boolean isLocalAndExists() {
return loc.isLocalAndExists(); return loc.isLocalAndExists();
} }
/** /**
* Returns whether the text file has been modified outside of this editor * Returns whether the text file has been modified outside of this editor since
* since the last load or save operation. Note that if this is a remote * the last load or save operation. Note that if this is a remote file, this
* file, this method will always return <code>false</code>. * method will always return <code>false</code>.
* <p> * <p>
* *
* This method may be used by applications to implement a reloading * This method may be used by applications to implement a reloading feature,
* feature, where the user is prompted to reload a file if it has been * where the user is prompted to reload a file if it has been modified since
* modified since their last open or save. * their last open or save.
* *
* @return Whether the text file has been modified outside of this * @return Whether the text file has been modified outside of this editor.
* editor.
* @see #getLastSaveOrLoadTime() * @see #getLastSaveOrLoadTime()
*/ */
public boolean isModifiedOutsideEditor() { public boolean isModifiedOutsideEditor() {
return loc.getActualLastModified() > getLastSaveOrLoadTime(); return loc.getActualLastModified() > getLastSaveOrLoadTime();
} }
/** /**
* Returns whether or not the text area should be treated as read-only. * Returns whether or not the text area should be treated as read-only.
* *
@@ -416,22 +396,18 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
public boolean isReadOnly() { public boolean isReadOnly() {
return readOnly; return readOnly;
} }
/** /**
* Loads the specified file in this editor. This method fires a property * Loads the specified file in this editor. This method fires a property change
* change event of type {@link #FULL_PATH_PROPERTY}. * event of type {@link #FULL_PATH_PROPERTY}.
* *
* @param loc * @param loc The location of the file to load. This cannot be
* The location of the file to load. This cannot be * <code>null</code>.
* <code>null</code>. * @param defaultEnc The encoding to use when loading/saving the file. This
* @param defaultEnc * encoding will only be used if the file is not Unicode. If
* The encoding to use when loading/saving the file. * this value is <code>null</code>, the system default
* This encoding will only be used if the file is not Unicode. * encoding is used.
* If this value is <code>null</code>, the system default * @throws IOException If an IO error occurs.
* encoding
* is used.
* @throws IOException
* If an IO error occurs.
* @see #save() * @see #save()
* @see #saveAs(FileLocation) * @see #saveAs(FileLocation)
*/ */
@@ -468,25 +444,24 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
discardAllEdits(); discardAllEdits();
firePropertyChange(FULL_PATH_PROPERTY, old, getFileFullPath()); firePropertyChange(FULL_PATH_PROPERTY, old, getFileFullPath());
} }
/** /**
* Reloads this file from disk. The file must exist for this operation * Reloads this file from disk. The file must exist for this operation to not
* to not throw an exception. * throw an exception.
* <p> * <p>
* *
* The file's "dirty" state will be set to <code>false</code> after this * The file's "dirty" state will be set to <code>false</code> after this
* operation. If this is a local file, its "last modified" time is * operation. If this is a local file, its "last modified" time is updated to
* updated to reflect that of the actual file. * reflect that of the actual file.
* <p> * <p>
* *
* Note that if the file has been modified on disk, and is now a Unicode * Note that if the file has been modified on disk, and is now a Unicode
* encoding when before it wasn't (or if it is a different Unicode now), * encoding when before it wasn't (or if it is a different Unicode now), this
* this will cause this {@link TextEditorPane}'s encoding to change. * will cause this {@link TextEditorPane}'s encoding to change. Otherwise, the
* Otherwise, the file's encoding will stay the same. * file's encoding will stay the same.
* *
* @throws IOException * @throws IOException If the file does not exist, or if an IO error occurs
* If the file does not exist, or if an IO error * reading the file.
* occurs reading the file.
* @see #isLocalAndExists() * @see #isLocalAndExists()
*/ */
public void reload() throws IOException { public void reload() throws IOException {
@@ -504,12 +479,11 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
syncLastSaveOrLoadTimeToActualFile(); syncLastSaveOrLoadTimeToActualFile();
discardAllEdits(); // Prevent user from being able to undo the reload discardAllEdits(); // Prevent user from being able to undo the reload
} }
/** /**
* Called whenever text is removed from this editor. * Called whenever text is removed from this editor.
* *
* @param e * @param e The document event.
* The document event.
*/ */
@Override @Override
public void removeUpdate(DocumentEvent e) { public void removeUpdate(DocumentEvent e) {
@@ -517,16 +491,15 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
setDirty(true); setDirty(true);
} }
} }
/** /**
* Saves the file in its current encoding. * Saves the file in its current encoding.
* <p> * <p>
* *
* The text area's "dirty" state is set to <code>false</code>, and if * The text area's "dirty" state is set to <code>false</code>, and if this is a
* this is a local file, its "last modified" time is updated. * local file, its "last modified" time is updated.
* *
* @throws IOException * @throws IOException If an IO error occurs.
* If an IO error occurs.
* @see #saveAs(FileLocation) * @see #saveAs(FileLocation)
* @see #load(FileLocation, String) * @see #load(FileLocation, String)
*/ */
@@ -535,15 +508,13 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
setDirty(false); setDirty(false);
syncLastSaveOrLoadTimeToActualFile(); syncLastSaveOrLoadTimeToActualFile();
} }
/** /**
* Saves this file in a new local location. This method fires a property * Saves this file in a new local location. This method fires a property change
* change event of type {@link #FULL_PATH_PROPERTY}. * event of type {@link #FULL_PATH_PROPERTY}.
* *
* @param loc * @param loc The location to save to.
* The location to save to. * @throws IOException If an IO error occurs.
* @throws IOException
* If an IO error occurs.
* @see #save() * @see #save()
* @see #load(FileLocation, String) * @see #load(FileLocation, String)
*/ */
@@ -556,14 +527,12 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
lastSaveOrLoadTime = loc.getActualLastModified(); lastSaveOrLoadTime = loc.getActualLastModified();
firePropertyChange(FULL_PATH_PROPERTY, old, getFileFullPath()); firePropertyChange(FULL_PATH_PROPERTY, old, getFileFullPath());
} }
/** /**
* Saves the text in this editor to the specified location. * Saves the text in this editor to the specified location.
* *
* @param loc * @param loc The location to save to.
* The location to save to. * @throws IOException If an IO error occurs.
* @throws IOException
* If an IO error occurs.
*/ */
private void saveImpl(FileLocation loc) throws IOException { private void saveImpl(FileLocation loc) throws IOException {
OutputStream out = loc.getOutputStream(); OutputStream out = loc.getOutputStream();
@@ -574,23 +543,22 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
w.close(); w.close();
} }
} }
/** /**
* Sets whether or not this text in this editor has unsaved changes. * Sets whether or not this text in this editor has unsaved changes. This fires
* This fires a property change event of type {@link #DIRTY_PROPERTY}. * a property change event of type {@link #DIRTY_PROPERTY}.
* <p> * <p>
* *
* Applications will usually have no need to call this method directly; the * Applications will usually have no need to call this method directly; the only
* only time you might have a need to call this method directly is if you * time you might have a need to call this method directly is if you have to
* have to initialize an instance of TextEditorPane with content that does * initialize an instance of TextEditorPane with content that does not come from
* not come from a file. <code>TextEditorPane</code> automatically sets its * a file. <code>TextEditorPane</code> automatically sets its own dirty flag
* own dirty flag when its content is edited, when its encoding is changed, * when its content is edited, when its encoding is changed, or when its line
* or when its line ending property is changed. It is cleared whenever * ending property is changed. It is cleared whenever <code>load()</code>,
* <code>load()</code>, <code>reload()</code>, <code>save()</code>, or * <code>reload()</code>, <code>save()</code>, or <code>saveAs()</code> are
* <code>saveAs()</code> are called. * called.
* *
* @param dirty * @param dirty Whether or not the text has been modified.
* Whether or not the text has been modified.
* @see #isDirty() * @see #isDirty()
*/ */
public void setDirty(boolean dirty) { public void setDirty(boolean dirty) {
@@ -599,12 +567,11 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
firePropertyChange(DIRTY_PROPERTY, !dirty, dirty); firePropertyChange(DIRTY_PROPERTY, !dirty, dirty);
} }
} }
/** /**
* Sets the document for this editor. * Sets the document for this editor.
* *
* @param doc * @param doc The new document.
* The new document.
*/ */
@Override @Override
public void setDocument(Document doc) { public void setDocument(Document doc) {
@@ -615,19 +582,16 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
super.setDocument(doc); super.setDocument(doc);
doc.addDocumentListener(this); doc.addDocumentListener(this);
} }
/** /**
* Sets the encoding to use when reading or writing this file. This * Sets the encoding to use when reading or writing this file. This method sets
* method sets the editor's dirty flag when the encoding is changed, and * the editor's dirty flag when the encoding is changed, and fires a property
* fires a property change event of type {@link #ENCODING_PROPERTY}. * change event of type {@link #ENCODING_PROPERTY}.
* *
* @param encoding * @param encoding The new encoding.
* The new encoding. * @throws UnsupportedCharsetException If the encoding is not supported.
* @throws UnsupportedCharsetException * @throws NullPointerException If <code>encoding</code> is
* If the encoding is not supported. * <code>null</code>.
* @throws NullPointerException
* If <code>encoding</code> is
* <code>null</code>.
* @see #getEncoding() * @see #getEncoding()
*/ */
public void setEncoding(String encoding) { public void setEncoding(String encoding) {
@@ -643,50 +607,43 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
setDirty(true); setDirty(true);
} }
} }
/** /**
* Sets the line separator sequence to use when this file is saved (e.g. * Sets the line separator sequence to use when this file is saved (e.g.
* "<code>\n</code>", "<code>\r\n</code>" or "<code>\r</code>"). * "<code>\n</code>", "<code>\r\n</code>" or "<code>\r</code>").
* *
* Besides parameter checking, this method is preferred over * Besides parameter checking, this method is preferred over
* <code>getDocument().putProperty()</code> because it sets the editor's * <code>getDocument().putProperty()</code> because it sets the editor's dirty
* dirty flag when the line separator is changed. * flag when the line separator is changed.
* *
* @param separator * @param separator The new line separator.
* The new line separator. * @throws NullPointerException If <code>separator</code> is
* @throws NullPointerException * <code>null</code>.
* If <code>separator</code> is * @throws IllegalArgumentException If <code>separator</code> is not one of
* <code>null</code>. * "<code>\n</code>", "<code>\r\n</code>" or
* @throws IllegalArgumentException * "<code>\r</code>".
* If <code>separator</code> is not one
* of "<code>\n</code>", "<code>\r\n</code>" or
* "<code>\r</code>".
* @see #getLineSeparator() * @see #getLineSeparator()
*/ */
public void setLineSeparator(String separator) { public void setLineSeparator(String separator) {
setLineSeparator(separator, true); setLineSeparator(separator, true);
} }
/** /**
* Sets the line separator sequence to use when this file is saved (e.g. * Sets the line separator sequence to use when this file is saved (e.g.
* "<code>\n</code>", "<code>\r\n</code>" or "<code>\r</code>"). * "<code>\n</code>", "<code>\r\n</code>" or "<code>\r</code>").
* *
* Besides parameter checking, this method is preferred over * Besides parameter checking, this method is preferred over
* <code>getDocument().putProperty()</code> because can set the editor's * <code>getDocument().putProperty()</code> because can set the editor's dirty
* dirty flag when the line separator is changed. * flag when the line separator is changed.
* *
* @param separator * @param separator The new line separator.
* The new line separator. * @param setDirty Whether the dirty flag should be set if the line separator
* @param setDirty * is changed.
* Whether the dirty flag should be set if the line * @throws NullPointerException If <code>separator</code> is
* separator is changed. * <code>null</code>.
* @throws NullPointerException * @throws IllegalArgumentException If <code>separator</code> is not one of
* If <code>separator</code> is * "<code>\n</code>", "<code>\r\n</code>" or
* <code>null</code>. * "<code>\r</code>".
* @throws IllegalArgumentException
* If <code>separator</code> is not one
* of "<code>\n</code>", "<code>\r\n</code>" or
* "<code>\r</code>".
* @see #getLineSeparator() * @see #getLineSeparator()
*/ */
public void setLineSeparator(String separator, boolean setDirty) { public void setLineSeparator(String separator, boolean setDirty) {
@@ -705,13 +662,12 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
} }
} }
} }
/** /**
* Sets whether or not this text area should be treated as read-only. * Sets whether or not this text area should be treated as read-only. This fires
* This fires a property change event of type {@link #READ_ONLY_PROPERTY}. * a property change event of type {@link #READ_ONLY_PROPERTY}.
* *
* @param readOnly * @param readOnly Whether or not the document is read-only.
* Whether or not the document is read-only.
* @see #isReadOnly() * @see #isReadOnly()
*/ */
public void setReadOnly(boolean readOnly) { public void setReadOnly(boolean readOnly) {
@@ -720,16 +676,16 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
firePropertyChange(READ_ONLY_PROPERTY, !readOnly, readOnly); firePropertyChange(READ_ONLY_PROPERTY, !readOnly, readOnly);
} }
} }
/** /**
* Syncs this text area's "last saved or loaded" time to that of the file * Syncs this text area's "last saved or loaded" time to that of the file being
* being edited, if that file is local and exists. If the file is * edited, if that file is local and exists. If the file is remote or is local
* remote or is local but does not yet exist, nothing happens. * but does not yet exist, nothing happens.
* <p> * <p>
* *
* You normally do not have to call this method, as the "last saved or * You normally do not have to call this method, as the "last saved or loaded"
* loaded" time for {@link TextEditorPane}s is kept up-to-date internally * time for {@link TextEditorPane}s is kept up-to-date internally during such
* during such operations as {@link #save()}, {@link #reload()}, etc. * operations as {@link #save()}, {@link #reload()}, etc.
* *
* @see #getLastSaveOrLoadTime() * @see #getLastSaveOrLoadTime()
* @see #isModifiedOutsideEditor() * @see #isModifiedOutsideEditor()
@@ -739,7 +695,7 @@ public class TextEditorPane extends RSyntaxTextArea implements DocumentListener
lastSaveOrLoadTime = loc.getActualLastModified(); lastSaveOrLoadTime = loc.getActualLastModified();
} }
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
try { try {
TextEditorPane textArea = new TextEditorPane(); TextEditorPane textArea = new TextEditorPane();
+191 -244
View File
@@ -38,195 +38,173 @@ import javax.swing.text.TabExpander;
* @version 0.3 * @version 0.3
*/ */
public interface Token extends TokenTypes { public interface Token extends TokenTypes {
/** /**
* Appends HTML code for painting this token, using the given text area's * Appends HTML code for painting this token, using the given text area's color
* color scheme. * scheme.
* *
* @param sb * @param sb The buffer to append to.
* The buffer to append to. * @param textArea The text area whose color scheme to use.
* @param textArea * @param fontFamily Whether to include the font family in the HTML for this
* The text area whose color scheme to use. * token. You can pass <code>false</code> for this parameter
* @param fontFamily * if, for example, you are making all your HTML be
* Whether to include the font family in the HTML for * monospaced, and don't want any crazy fonts being used in
* this token. You can pass <code>false</code> for this parameter * the editor to be reflected in your HTML.
* if, for example, you are making all your HTML be monospaced,
* and don't want any crazy fonts being used in the editor to be
* reflected in your HTML.
* @return The buffer appended to. * @return The buffer appended to.
* @see #getHTMLRepresentation(RSyntaxTextArea) * @see #getHTMLRepresentation(RSyntaxTextArea)
*/ */
StringBuilder appendHTMLRepresentation(StringBuilder sb, RSyntaxTextArea textArea, boolean fontFamily); StringBuilder appendHTMLRepresentation(StringBuilder sb, RSyntaxTextArea textArea, boolean fontFamily);
/** /**
* Appends HTML code for painting this token, using the given text area's * Appends HTML code for painting this token, using the given text area's color
* color scheme. * scheme.
* *
* @param sb * @param sb The buffer to append to.
* The buffer to append to. * @param textArea The text area whose color scheme to use.
* @param textArea * @param fontFamily Whether to include the font family in the HTML for this
* The text area whose color scheme to use. * token. You can pass <code>false</code> for this parameter
* @param fontFamily * if, for example, you are making all your HTML be
* Whether to include the font family in the HTML for * monospaced, and don't want any crazy fonts being used in
* this token. You can pass <code>false</code> for this parameter * the editor to be reflected in your HTML.
* if, for example, you are making all your HTML be monospaced, * @param tabsToSpaces Whether to convert tabs into spaces.
* and don't want any crazy fonts being used in the editor to be
* reflected in your HTML.
* @param tabsToSpaces
* Whether to convert tabs into spaces.
* @return The buffer appended to. * @return The buffer appended to.
* @see #getHTMLRepresentation(RSyntaxTextArea) * @see #getHTMLRepresentation(RSyntaxTextArea)
*/ */
StringBuilder appendHTMLRepresentation(StringBuilder sb, RSyntaxTextArea textArea, boolean fontFamily, boolean tabsToSpaces); StringBuilder appendHTMLRepresentation(StringBuilder sb, RSyntaxTextArea textArea, boolean fontFamily,
boolean tabsToSpaces);
/** /**
* Returns the character at the specified offset in the token. * Returns the character at the specified offset in the token.
* *
* @param index * @param index The index. This should be in the range
* The index. This should be in the range * <code>0-({@link #length()}-1)</code>.
* <code>0-({@link #length()}-1)</code>.
* @return The character. * @return The character.
* @see #length() * @see #length()
*/ */
char charAt(int index); char charAt(int index);
/** /**
* Returns whether the token straddles the specified position in the * Returns whether the token straddles the specified position in the document.
* document.
* *
* @param pos * @param pos The position in the document to check.
* The position in the document to check.
* @return Whether the specified position is straddled by this token. * @return Whether the specified position is straddled by this token.
*/ */
boolean containsPosition(int pos); boolean containsPosition(int pos);
/** /**
* Returns the position in the token's internal char array corresponding * Returns the position in the token's internal char array corresponding to the
* to the specified document position. * specified document position.
* <p> * <p>
* Note that this method does NOT do any bounds checking; you can pass in * Note that this method does NOT do any bounds checking; you can pass in a
* a document position that does not correspond to a position in this * document position that does not correspond to a position in this token, and
* token, and you will not receive an Exception or any other notification; * you will not receive an Exception or any other notification; it is up to the
* it is up to the caller to ensure valid input. * caller to ensure valid input.
* *
* @param pos * @param pos A position in the document that is represented by this token.
* A position in the document that is represented by this token. * @return The corresponding token position &gt;= <code>textOffset</code> and
* @return The corresponding token position &gt;= <code>textOffset</code> * &lt; <code>textOffset+textCount</code>.
* and &lt; <code>textOffset+textCount</code>.
* @see #tokenToDocument * @see #tokenToDocument
*/ */
int documentToToken(int pos); int documentToToken(int pos);
/** /**
* Returns whether this token's lexeme ends with the specified characters. * Returns whether this token's lexeme ends with the specified characters.
* *
* @param ch * @param ch The characters.
* The characters.
* @return Whether this token's lexeme ends with the specified characters. * @return Whether this token's lexeme ends with the specified characters.
* @see #startsWith(char[]) * @see #startsWith(char[])
*/ */
boolean endsWith(char[] ch); boolean endsWith(char[] ch);
/** /**
* Returns the end offset of this token in the document (exclusive). In * Returns the end offset of this token in the document (exclusive). In other
* other words, the token ranges from * words, the token ranges from <code>[getOffset(), getEndOffset())</code>.
* <code>[getOffset(), getEndOffset())</code>.
* *
* @return The end offset of this token. * @return The end offset of this token.
* @see #getOffset() * @see #getOffset()
*/ */
int getEndOffset(); int getEndOffset();
/** /**
* Returns a <code>String</code> containing HTML code for painting this * Returns a <code>String</code> containing HTML code for painting this token,
* token, using the given text area's color scheme. * using the given text area's color scheme.
* *
* @param textArea * @param textArea The text area whose color scheme to use.
* The text area whose color scheme to use.
* @return The HTML representation of the token. * @return The HTML representation of the token.
* @see #appendHTMLRepresentation(StringBuilder, RSyntaxTextArea, boolean) * @see #appendHTMLRepresentation(StringBuilder, RSyntaxTextArea, boolean)
*/ */
String getHTMLRepresentation(RSyntaxTextArea textArea); String getHTMLRepresentation(RSyntaxTextArea textArea);
/** /**
* Returns the language index of this token. * Returns the language index of this token.
* *
* @return The language index. A value of <code>0</code> denotes the * @return The language index. A value of <code>0</code> denotes the "main"
* "main" language, any positive value denotes a specific secondary * language, any positive value denotes a specific secondary language.
* language.
* @see #setLanguageIndex(int) * @see #setLanguageIndex(int)
*/ */
int getLanguageIndex(); int getLanguageIndex();
/** /**
* Returns the last token in this list that is not whitespace or a * Returns the last token in this list that is not whitespace or a comment.
* comment.
* *
* @return The last non-comment, non-whitespace token, or <code>null</code> * @return The last non-comment, non-whitespace token, or <code>null</code> if
* if there isn't one. * there isn't one.
*/ */
Token getLastNonCommentNonWhitespaceToken(); Token getLastNonCommentNonWhitespaceToken();
/** /**
* Returns the last paintable token in this token list, or <code>null</code> * Returns the last paintable token in this token list, or <code>null</code> if
* if there is no paintable token. * there is no paintable token.
* *
* @return The last paintable token in this token list. * @return The last paintable token in this token list.
*/ */
Token getLastPaintableToken(); Token getLastPaintableToken();
/** /**
* Returns the text of this token, as a string. * Returns the text of this token, as a string.
* <p> * <p>
* *
* Note that this method isn't used much by the * Note that this method isn't used much by the <code>ryntaxtextarea</code>
* <code>ryntaxtextarea</code> package internally, as it tries to limit * package internally, as it tries to limit memory allocation.
* memory allocation.
* *
* @return The text of this token. * @return The text of this token.
*/ */
String getLexeme(); String getLexeme();
/** /**
* Determines the offset into this token list (i.e., into the * Determines the offset into this token list (i.e., into the document) that
* document) that covers pixel location <code>x</code> if the token list * covers pixel location <code>x</code> if the token list starts at pixel
* starts at pixel location <code>x0</code> * location <code>x0</code>
* <p> * <p>
* . * . This method will return the document position "closest" to the x-coordinate
* This method will return the document position "closest" to the * (i.e., if they click on the "right-half" of the <code>w</code> in
* x-coordinate (i.e., if they click on the "right-half" of the * <code>awe</code>, the caret will be placed in between the <code>w</code> and
* <code>w</code> in <code>awe</code>, the caret will be placed in * <code>e</code>; similarly, clicking on the left-half places the caret between
* between the <code>w</code> and <code>e</code>; similarly, clicking on * the <code>a</code> and <code>w</code>). This makes it useful for methods such
* the left-half places the caret between the <code>a</code> and * as <code>viewToModel</code> found in <code>javax.swing.text.View</code>
* <code>w</code>). This makes it useful for methods such as
* <code>viewToModel</code> found in <code>javax.swing.text.View</code>
* subclasses. * subclasses.
* *
* @param textArea * @param textArea The text area from which the token list was derived.
* The text area from which the token list was derived. * @param e How to expand tabs.
* @param e * @param x0 The pixel x-location that is the beginning of
* How to expand tabs. * <code>tokenList</code>.
* @param x0 * @param x The pixel-position for which you want to get the
* The pixel x-location that is the beginning of * corresponding offset.
* <code>tokenList</code>. * @return The position (in the document, NOT into the token list!) that covers
* @param x * the pixel location. If <code>tokenList</code> is <code>null</code> or
* The pixel-position for which you want to get the corresponding * has type <code>Token.NULL</code>, then <code>-1</code> is returned;
* offset. * the caller should recognize this and return the actual end position
* @return The position (in the document, NOT into the token list!) that * of the (empty) line.
* covers the pixel location. If <code>tokenList</code> is
* <code>null</code> or has type <code>Token.NULL</code>, then
* <code>-1</code> is returned; the caller should recognize this and
* return the actual end position of the (empty) line.
*/ */
int getListOffset(RSyntaxTextArea textArea, TabExpander e, float x0, float x); int getListOffset(RSyntaxTextArea textArea, TabExpander e, float x0, float x);
/** /**
* Returns the token after this one in the linked list. * Returns the token after this one in the linked list.
* *
* @return The next token. * @return The next token.
*/ */
Token getNextToken(); Token getNextToken();
/** /**
* Returns the offset into the document at which this token resides. * Returns the offset into the document at which this token resides.
* *
@@ -234,49 +212,43 @@ public interface Token extends TokenTypes {
* @see #getEndOffset() * @see #getEndOffset()
*/ */
int getOffset(); int getOffset();
/** /**
* Returns the position in the document that represents the last character * Returns the position in the document that represents the last character in
* in the token that will fit into <code>endBeforeX-startX</code> pixels. * the token that will fit into <code>endBeforeX-startX</code> pixels. For
* For example, if you're using a monospaced 8-pixel-per-character font, * example, if you're using a monospaced 8-pixel-per-character font, have the
* have the token "while" and <code>startX</code> is <code>0</code> and * token "while" and <code>startX</code> is <code>0</code> and
* <code>endBeforeX</code> is <code>30</code>, this method will return the * <code>endBeforeX</code> is <code>30</code>, this method will return the
* document position of the "i" in "while", because the "i" ends at pixel * document position of the "i" in "while", because the "i" ends at pixel
* <code>24</code>, while the "l" ends at <code>32</code>. If not even the * <code>24</code>, while the "l" ends at <code>32</code>. If not even the first
* first character fits in <code>endBeforeX-startX</code>, the first * character fits in <code>endBeforeX-startX</code>, the first character's
* character's position is still returned so calling methods don't go into * position is still returned so calling methods don't go into infinite loops.
* infinite loops.
* *
* @param textArea * @param textArea The text area in which this token is being painted.
* The text area in which this token is being painted. * @param e How to expand tabs.
* @param e * @param startX The x-coordinate at which the token will be painted. This
* How to expand tabs. * is needed because of tabs.
* @param startX * @param endBeforeX The x-coordinate for which you want to find the last
* The x-coordinate at which the token will be painted. This * character of <code>t</code> which comes before it.
* is needed because of tabs. * @return The last document position that will fit in the specified amount of
* @param endBeforeX * pixels.
* The x-coordinate for which you want to find the last
* character of <code>t</code> which comes before it.
* @return The last document position that will fit in the specified amount
* of pixels.
*/ */
/* /*
* @see #getTokenListOffsetBeforeX * @see #getTokenListOffsetBeforeX FIXME: This method does not compute
* FIXME: This method does not compute correctly! It needs to be abstract * correctly! It needs to be abstract and implemented by subclasses.
* and implemented by subclasses.
*/ */
int getOffsetBeforeX(RSyntaxTextArea textArea, TabExpander e, float startX, float endBeforeX); int getOffsetBeforeX(RSyntaxTextArea textArea, TabExpander e, float startX, float endBeforeX);
/** /**
* Returns the character array backing the lexeme of this token. This * Returns the character array backing the lexeme of this token. This value
* value should be treated as read-only. * should be treated as read-only.
* *
* @return A character array containing the lexeme of this token. * @return A character array containing the lexeme of this token.
* @see #getTextOffset() * @see #getTextOffset()
* @see #length() * @see #length()
*/ */
char[] getTextArray(); char[] getTextArray();
/** /**
* Returns the offset into the character array of the lexeme in * Returns the offset into the character array of the lexeme in
* {@link #getTextArray()}. * {@link #getTextArray()}.
@@ -285,7 +257,7 @@ public interface Token extends TokenTypes {
* @see #getTextArray() * @see #getTextArray()
*/ */
int getTextOffset(); int getTextOffset();
/** /**
* Returns the type of this token. * Returns the type of this token.
* *
@@ -294,47 +266,39 @@ public interface Token extends TokenTypes {
* @see #setType(int) * @see #setType(int)
*/ */
int getType(); int getType();
/** /**
* Returns the width of this token given the specified parameters. * Returns the width of this token given the specified parameters.
* *
* @param textArea * @param textArea The text area in which the token is being painted.
* The text area in which the token is being painted. * @param e Describes how to expand tabs. This parameter cannot be
* @param e * <code>null</code>.
* Describes how to expand tabs. This parameter cannot be * @param x0 The pixel-location at which the token begins. This is needed
* <code>null</code>. * because of tabs.
* @param x0
* The pixel-location at which the token begins. This is needed
* because of tabs.
* @return The width of the token, in pixels. * @return The width of the token, in pixels.
* @see #getWidthUpTo * @see #getWidthUpTo
*/ */
float getWidth(RSyntaxTextArea textArea, TabExpander e, float x0); float getWidth(RSyntaxTextArea textArea, TabExpander e, float x0);
/** /**
* Returns the width of a specified number of characters in this token. * Returns the width of a specified number of characters in this token. For
* For example, for the token "while", specifying a value of <code>3</code> * example, for the token "while", specifying a value of <code>3</code> here
* here returns the width of the "whi" portion of the token. * returns the width of the "whi" portion of the token.
* *
* @param numChars * @param numChars The number of characters for which to get the width.
* The number of characters for which to get the width. * @param textArea The text area in which the token is being painted.
* @param textArea * @param e How to expand tabs. This value cannot be <code>null</code>.
* The text area in which the token is being painted. * @param x0 The pixel-location at which this token begins. This is needed
* @param e * because of tabs.
* How to expand tabs. This value cannot be <code>null</code>.
* @param x0
* The pixel-location at which this token begins. This is needed
* because of tabs.
* @return The width of the specified number of characters in this token. * @return The width of the specified number of characters in this token.
* @see #getWidth * @see #getWidth
*/ */
float getWidthUpTo(int numChars, RSyntaxTextArea textArea, TabExpander e, float x0); float getWidthUpTo(int numChars, RSyntaxTextArea textArea, TabExpander e, float x0);
/** /**
* Returns whether this token's lexeme matches a specific character array. * Returns whether this token's lexeme matches a specific character array.
* *
* @param lexeme * @param lexeme The lexeme to check for.
* The lexeme to check for.
* @return Whether this token has that lexeme. * @return Whether this token has that lexeme.
* @see #is(int, char[]) * @see #is(int, char[])
* @see #is(int, String) * @see #is(int, String)
@@ -342,19 +306,17 @@ public interface Token extends TokenTypes {
* @see #startsWith(char[]) * @see #startsWith(char[])
*/ */
boolean is(char[] lexeme); boolean is(char[] lexeme);
/** /**
* Returns whether this token is of the specified type, with the specified * Returns whether this token is of the specified type, with the specified
* lexeme. * lexeme.
* <p> * <p>
* This method is preferred over the other overload in performance-critical * This method is preferred over the other overload in performance-critical code
* code where this operation may be called frequently, since it does not * where this operation may be called frequently, since it does not involve any
* involve any String allocations. * String allocations.
* *
* @param type * @param type The type to check for.
* The type to check for. * @param lexeme The lexeme to check for.
* @param lexeme
* The lexeme to check for.
* @return Whether this token has that type and lexeme. * @return Whether this token has that type and lexeme.
* @see #is(int, String) * @see #is(int, String)
* @see #is(char[]) * @see #is(char[])
@@ -362,26 +324,24 @@ public interface Token extends TokenTypes {
* @see #startsWith(char[]) * @see #startsWith(char[])
*/ */
boolean is(int type, char[] lexeme); boolean is(int type, char[] lexeme);
/** /**
* Returns whether this token is of the specified type, with the specified * Returns whether this token is of the specified type, with the specified
* lexeme. * lexeme.
* <p> * <p>
* The other overload of this method is preferred over this one in * The other overload of this method is preferred over this one in
* performance-critical code, as this one involves a String allocation * performance-critical code, as this one involves a String allocation while the
* while the other does not. * other does not.
* *
* @param type * @param type The type to check for.
* The type to check for. * @param lexeme The lexeme to check for.
* @param lexeme
* The lexeme to check for.
* @return Whether this token has that type and lexeme. * @return Whether this token has that type and lexeme.
* @see #is(int, char[]) * @see #is(int, char[])
* @see #isSingleChar(int, char) * @see #isSingleChar(int, char)
* @see #startsWith(char[]) * @see #startsWith(char[])
*/ */
boolean is(int type, String lexeme); boolean is(int type, String lexeme);
/** /**
* Returns whether this token is a comment. * Returns whether this token is a comment.
* *
@@ -390,7 +350,7 @@ public interface Token extends TokenTypes {
* @see #isCommentOrWhitespace() * @see #isCommentOrWhitespace()
*/ */
boolean isComment(); boolean isComment();
/** /**
* Returns whether this token is a comment or whitespace. * Returns whether this token is a comment or whitespace.
* *
@@ -399,7 +359,7 @@ public interface Token extends TokenTypes {
* @see #isWhitespace() * @see #isWhitespace()
*/ */
boolean isCommentOrWhitespace(); boolean isCommentOrWhitespace();
/** /**
* Returns whether this token is a hyperlink. * Returns whether this token is a hyperlink.
* *
@@ -407,23 +367,23 @@ public interface Token extends TokenTypes {
* @see #setHyperlink(boolean) * @see #setHyperlink(boolean)
*/ */
boolean isHyperlink(); boolean isHyperlink();
/** /**
* Returns whether this token is an identifier. * Returns whether this token is an identifier.
* *
* @return Whether this token is an identifier. * @return Whether this token is an identifier.
*/ */
boolean isIdentifier(); boolean isIdentifier();
/** /**
* Returns whether this token is a {@link #SEPARATOR} representing a single * Returns whether this token is a {@link #SEPARATOR} representing a single left
* left curly brace. * curly brace.
* *
* @return Whether this token is a left curly brace. * @return Whether this token is a left curly brace.
* @see #isRightCurly() * @see #isRightCurly()
*/ */
boolean isLeftCurly(); boolean isLeftCurly();
/** /**
* Returns whether this token is a {@link #SEPARATOR} representing a single * Returns whether this token is a {@link #SEPARATOR} representing a single
* right curly brace. * right curly brace.
@@ -432,41 +392,38 @@ public interface Token extends TokenTypes {
* @see #isLeftCurly() * @see #isLeftCurly()
*/ */
boolean isRightCurly(); boolean isRightCurly();
/** /**
* Returns whether or not this token is "paintable;" i.e., whether or not * Returns whether or not this token is "paintable;" i.e., whether or not the
* the type of this token is one such that it has an associated syntax * type of this token is one such that it has an associated syntax style. What
* style. What this boils down to is whether the token type is greater * this boils down to is whether the token type is greater than
* than <code>Token.NULL</code>. * <code>Token.NULL</code>.
* *
* @return Whether or not this token is paintable. * @return Whether or not this token is paintable.
*/ */
boolean isPaintable(); boolean isPaintable();
/** /**
* Returns whether this token is the specified single character. * Returns whether this token is the specified single character.
* *
* @param ch * @param ch The character to check for.
* The character to check for.
* @return Whether this token's lexeme is the single character specified. * @return Whether this token's lexeme is the single character specified.
* @see #isSingleChar(int, char) * @see #isSingleChar(int, char)
*/ */
boolean isSingleChar(char ch); boolean isSingleChar(char ch);
/** /**
* Returns whether this token is the specified single character, and of a * Returns whether this token is the specified single character, and of a
* specific type. * specific type.
* *
* @param type * @param type The token type.
* The token type. * @param ch The character to check for.
* @param ch
* The character to check for.
* @return Whether this token is of the specified type, and with a lexeme * @return Whether this token is of the specified type, and with a lexeme
* Equaling the single character specified. * Equaling the single character specified.
* @see #isSingleChar(char) * @see #isSingleChar(char)
*/ */
boolean isSingleChar(int type, char ch); boolean isSingleChar(int type, char ch);
/** /**
* Returns whether or not this token is whitespace. * Returns whether or not this token is whitespace.
* *
@@ -475,7 +432,7 @@ public interface Token extends TokenTypes {
* @see #isCommentOrWhitespace() * @see #isCommentOrWhitespace()
*/ */
boolean isWhitespace(); boolean isWhitespace();
/** /**
* Returns the length of this token. * Returns the length of this token.
* *
@@ -483,87 +440,77 @@ public interface Token extends TokenTypes {
* @see #getOffset() * @see #getOffset()
*/ */
int length(); int length();
/** /**
* Returns the bounding box for the specified document location. The * Returns the bounding box for the specified document location. The location
* location must be in the specified token list; if it isn't, * must be in the specified token list; if it isn't, <code>null</code> is
* <code>null</code> is returned. * returned.
* *
* @param textArea * @param textArea The text area from which the token list was derived.
* The text area from which the token list was derived. * @param e How to expand tabs.
* @param e * @param pos The position in the document for which to get the bounding
* How to expand tabs. * box in the view.
* @param pos * @param x0 The pixel x-location that is the beginning of
* The position in the document for which to get the bounding * <code>tokenList</code>.
* box in the view. * @param rect The rectangle in which we'll be returning the results. This
* @param x0 * object is reused to keep from frequent memory allocations.
* The pixel x-location that is the beginning of
* <code>tokenList</code>.
* @param rect
* The rectangle in which we'll be returning the results. This
* object is reused to keep from frequent memory allocations.
* @return The bounding box for the specified position in the model. * @return The bounding box for the specified position in the model.
*/ */
Rectangle listOffsetToView(RSyntaxTextArea textArea, TabExpander e, int pos, int x0, Rectangle rect); Rectangle listOffsetToView(RSyntaxTextArea textArea, TabExpander e, int pos, int x0, Rectangle rect);
/** /**
* Sets whether this token is a hyperlink. * Sets whether this token is a hyperlink.
* *
* @param hyperlink * @param hyperlink Whether this token is a hyperlink.
* Whether this token is a hyperlink.
* @see #isHyperlink() * @see #isHyperlink()
*/ */
void setHyperlink(boolean hyperlink); void setHyperlink(boolean hyperlink);
/** /**
* Sets the language index for this token. If this value is positive, it * Sets the language index for this token. If this value is positive, it denotes
* denotes a specific "secondary" language this token represents (such as * a specific "secondary" language this token represents (such as JavaScript
* JavaScript code or CSS embedded in an HTML file). If this value is * code or CSS embedded in an HTML file). If this value is <code>0</code>, this
* <code>0</code>, this token is in the "main" language being edited. * token is in the "main" language being edited. Negative values are invalid and
* Negative values are invalid and treated as <code>0</code>. * treated as <code>0</code>.
* *
* @param languageIndex * @param languageIndex The new language index. A value of <code>0</code>
* The new language index. A value of * denotes the "main" language, any positive value denotes
* <code>0</code> denotes the "main" language, any positive value * a specific secondary language. Negative values will be
* denotes a specific secondary language. Negative values will * treated as <code>0</code>.
* be treated as <code>0</code>.
* @see #getLanguageIndex() * @see #getLanguageIndex()
*/ */
void setLanguageIndex(int languageIndex); void setLanguageIndex(int languageIndex);
/** /**
* Sets the type of this token. * Sets the type of this token.
* *
* @param type * @param type The new token type.
* The new token type.
* @see TokenTypes * @see TokenTypes
* @see #getType() * @see #getType()
*/ */
void setType(int type); void setType(int type);
/** /**
* Returns whether this token starts with the specified characters. * Returns whether this token starts with the specified characters.
* *
* @param chars * @param chars The characters.
* The characters.
* @return Whether this token starts with those characters. * @return Whether this token starts with those characters.
* @see #endsWith(char[]) * @see #endsWith(char[])
* @see #is(int, char[]) * @see #is(int, char[])
*/ */
boolean startsWith(char[] chars); boolean startsWith(char[] chars);
/** /**
* Returns the position in the document corresponding to the specified * Returns the position in the document corresponding to the specified position
* position in this token's internal char array (<code>textOffset</code> - * in this token's internal char array (<code>textOffset</code> -
* <code>textOffset+textCount-1</code>). * <code>textOffset+textCount-1</code>).
* <p> * <p>
* Note that this method does NOT do any bounds checking; you can pass in * Note that this method does NOT do any bounds checking; you can pass in an
* an invalid token position, and you will not receive an Exception or any * invalid token position, and you will not receive an Exception or any other
* other indication that the returned document position is invalid. It is * indication that the returned document position is invalid. It is up to the
* up to the user to ensure valid input. * user to ensure valid input.
* *
* @param pos * @param pos A position in the token's internal char array
* A position in the token's internal char array
* (<code>textOffset</code> - <code>textOffset+textCount</code>). * (<code>textOffset</code> - <code>textOffset+textCount</code>).
* @return The corresponding position in the document. * @return The corresponding position in the document.
* @see #documentToToken(int) * @see #documentToToken(int)
@@ -15,52 +15,42 @@ import javax.swing.text.Segment;
* @version 0.1 * @version 0.1
*/ */
interface TokenFactory { interface TokenFactory {
/** /**
* Returns a null token. * Returns a null token.
* *
* @return A null token. * @return A null token.
*/ */
TokenImpl createToken(); TokenImpl createToken();
/** /**
* Returns a token. * Returns a token.
* *
* @param line * @param line The segment from which to get the token's text.
* The segment from which to get the token's text. * @param beg The starting offset of the token's text in the segment.
* @param beg * @param end The ending offset of the token's text in the segment.
* The starting offset of the token's text in the segment. * @param startOffset The offset in the document of the token.
* @param end * @param type The type of token.
* The ending offset of the token's text in the segment.
* @param startOffset
* The offset in the document of the token.
* @param type
* The type of token.
* @return The token. * @return The token.
*/ */
TokenImpl createToken(final Segment line, final int beg, final int end, final int startOffset, final int type); TokenImpl createToken(final Segment line, final int beg, final int end, final int startOffset, final int type);
/** /**
* Returns a token. * Returns a token.
* *
* @param line * @param line The char array from which to get the token's text.
* The char array from which to get the token's text. * @param beg The starting offset of the token's text in the char array.
* @param beg * @param end The ending offset of the token's text in the char array.
* The starting offset of the token's text in the char array. * @param startOffset The offset in the document of the token.
* @param end * @param type The type of token.
* The ending offset of the token's text in the char array.
* @param startOffset
* The offset in the document of the token.
* @param type
* The type of token.
* @return The token. * @return The token.
*/ */
TokenImpl createToken(final char[] line, final int beg, final int end, final int startOffset, final int type); TokenImpl createToken(final char[] line, final int beg, final int end, final int startOffset, final int type);
/** /**
* Resets the state of this token maker. This method should be called * Resets the state of this token maker. This method should be called by the
* by the <code>TokenMaker</code> every time a token list is generated for * <code>TokenMaker</code> every time a token list is generated for a new line
* a new line so the tokens can be reused. * so the tokens can be reused.
*/ */
void resetAllTokens(); void resetAllTokens();
} }
@@ -16,16 +16,15 @@ import java.util.Iterator;
* @version 1.0 * @version 1.0
*/ */
class TokenIterator implements Iterator<Token> { class TokenIterator implements Iterator<Token> {
private RSyntaxDocument doc; private RSyntaxDocument doc;
private int curLine; private int curLine;
private Token token; private Token token;
/** /**
* Constructor. * Constructor.
* *
* @param doc * @param doc The document whose tokens we should iterate over.
* The document whose tokens we should iterate over.
*/ */
TokenIterator(RSyntaxDocument doc) { TokenIterator(RSyntaxDocument doc) {
this.doc = doc; this.doc = doc;
@@ -36,11 +35,11 @@ class TokenIterator implements Iterator<Token> {
loadTokenListForCurLine(); loadTokenListForCurLine();
} }
} }
private int getLineCount() { private int getLineCount() {
return doc.getDefaultRootElement().getElementCount(); return doc.getDefaultRootElement().getElementCount();
} }
/** /**
* Returns whether any more paintable tokens are in the document. * Returns whether any more paintable tokens are in the document.
* *
@@ -51,7 +50,7 @@ class TokenIterator implements Iterator<Token> {
public boolean hasNext() { public boolean hasNext() {
return token != null; return token != null;
} }
private void loadTokenListForCurLine() { private void loadTokenListForCurLine() {
token = doc.getTokenListForLine(curLine); token = doc.getTokenListForLine(curLine);
if (token != null && !token.isPaintable()) { if (token != null && !token.isPaintable()) {
@@ -59,7 +58,7 @@ class TokenIterator implements Iterator<Token> {
token = null; token = null;
} }
} }
/** /**
* Returns the next paintable token in the document. * Returns the next paintable token in the document.
* *
@@ -96,13 +95,12 @@ class TokenIterator implements Iterator<Token> {
} }
return t; return t;
} }
/** /**
* Always throws {@link UnsupportedOperationException}, as * Always throws {@link UnsupportedOperationException}, as <code>Token</code>
* <code>Token</code> removal is not supported. * removal is not supported.
* *
* @throws UnsupportedOperationException * @throws UnsupportedOperationException always.
* always.
*/ */
@Override @Override
public void remove() { public void remove() {
+84 -106
View File
@@ -12,8 +12,8 @@ import javax.swing.text.Segment;
/** /**
* An implementation of <code>TokenMaker</code> is a class that turns text into * An implementation of <code>TokenMaker</code> is a class that turns text into
* a linked list of <code>Token</code>s for syntax highlighting * a linked list of <code>Token</code>s for syntax highlighting in a particular
* in a particular language. * language.
* *
* @see Token * @see Token
* @see AbstractTokenMaker * @see AbstractTokenMaker
@@ -22,164 +22,142 @@ import javax.swing.text.Segment;
* @version 0.2 * @version 0.2
*/ */
public interface TokenMaker { public interface TokenMaker {
/** /**
* Adds a null token to the end of the current linked list of tokens. * Adds a null token to the end of the current linked list of tokens. This
* This should be put at the end of the linked list whenever the last * should be put at the end of the linked list whenever the last token on the
* token on the current line is NOT a multi-line token. * current line is NOT a multi-line token.
*/ */
public void addNullToken(); public void addNullToken();
/** /**
* Adds the token specified to the current linked list of tokens. * Adds the token specified to the current linked list of tokens.
* *
* @param array * @param array The character array from which to get the text.
* The character array from which to get the text. * @param start Start offset in <code>segment</code> of token.
* @param start * @param end End offset in <code>segment</code> of token.
* Start offset in <code>segment</code> of token. * @param tokenType The token's type.
* @param end * @param startOffset The offset in the document at which this token occurs.
* End offset in <code>segment</code> of token.
* @param tokenType
* The token's type.
* @param startOffset
* The offset in the document at which this token
* occurs.
*/ */
public void addToken(char[] array, int start, int end, int tokenType, int startOffset); public void addToken(char[] array, int start, int end, int tokenType, int startOffset);
/** /**
* Returns the closest {@link TokenTypes "standard" token type} for a given * Returns the closest {@link TokenTypes "standard" token type} for a given
* "internal" token type (e.g. one whose value is <code>&lt; 0</code>). * "internal" token type (e.g. one whose value is <code>&lt; 0</code>).
* *
* @param type * @param type The token type.
* The token type. * @return The closest "standard" token type. If a mapping is not defined for
* @return The closest "standard" token type. If a mapping is not defined * this language, then <code>type</code> is returned.
* for this language, then <code>type</code> is returned.
*/ */
public int getClosestStandardTokenTypeForInternalType(int type); public int getClosestStandardTokenTypeForInternalType(int type);
/** /**
* Returns whether this programming language uses curly braces * Returns whether this programming language uses curly braces ('<code>{</code>'
* ('<code>{</code>' and '<code>}</code>') to denote code blocks. * and '<code>}</code>') to denote code blocks.
* *
* @param languageIndex * @param languageIndex The language index at the offset in question. Since some
* The language index at the offset in question. * <code>TokenMaker</code>s effectively have nested
* Since some <code>TokenMaker</code>s effectively have nested * languages (such as JavaScript in HTML), this parameter
* languages (such as JavaScript in HTML), this parameter tells * tells the <code>TokenMaker</code> what sub-language to
* the * look at.
* <code>TokenMaker</code> what sub-language to look at.
* @return Whether curly braces denote code blocks. * @return Whether curly braces denote code blocks.
*/ */
public boolean getCurlyBracesDenoteCodeBlocks(int languageIndex); public boolean getCurlyBracesDenoteCodeBlocks(int languageIndex);
/** /**
* Returns the last token on this line's type if the token is "unfinished", * Returns the last token on this line's type if the token is "unfinished", or
* or {@link Token#NULL} if it was finished. For example, if C-style * {@link Token#NULL} if it was finished. For example, if C-style syntax
* syntax highlighting is being implemented, and <code>text</code> * highlighting is being implemented, and <code>text</code> contained a line of
* contained a line of code that contained the beginning of a comment but * code that contained the beginning of a comment but no end-comment marker
* no end-comment marker ("*\/"), then this method would return * ("*\/"), then this method would return {@link Token#COMMENT_MULTILINE} for
* {@link Token#COMMENT_MULTILINE} for that line. This is useful * that line. This is useful for doing syntax highlighting.
* for doing syntax highlighting.
* *
* @param text * @param text The line of tokens to examine.
* The line of tokens to examine. * @param initialTokenType The token type to start with (i.e., the value of
* @param initialTokenType * <code>getLastTokenTypeOnLine</code> for the line
* The token type to start with (i.e., the value * before <code>text</code>).
* of <code>getLastTokenTypeOnLine</code> for the line before * @return The last token on this line's type, or {@link Token#NULL} if the line
* <code>text</code>). * was completed.
* @return The last token on this line's type, or {@link Token#NULL}
* if the line was completed.
*/ */
public int getLastTokenTypeOnLine(Segment text, int initialTokenType); public int getLastTokenTypeOnLine(Segment text, int initialTokenType);
/** /**
* Returns the text to place at the beginning and end of a * Returns the text to place at the beginning and end of a line to "comment" it
* line to "comment" it in this programming language. * in this programming language.
* *
* @param languageIndex * @param languageIndex The language index at the offset in question. Since some
* The language index at the offset in question. * <code>TokenMaker</code>s effectively have nested
* Since some <code>TokenMaker</code>s effectively have nested * languages (such as JavaScript in HTML), this parameter
* languages (such as JavaScript in HTML), this parameter tells * tells the <code>TokenMaker</code> what sub-language to
* the * look at.
* <code>TokenMaker</code> what sub-language to look at. * @return The start and end strings to add to a line to "comment" it out. A
* @return The start and end strings to add to a line to "comment" * <code>null</code> value for either means there is no string to add
* it out. A <code>null</code> value for either means there * for that part. A value of <code>null</code> for the array means this
* is no string to add for that part. A value of * language does not support commenting/uncommenting lines.
* <code>null</code> for the array means this language
* does not support commenting/uncommenting lines.
*/ */
public String[] getLineCommentStartAndEnd(int languageIndex); public String[] getLineCommentStartAndEnd(int languageIndex);
/** /**
* Returns an action to handle "insert break" key presses (i.e. Enter). * Returns an action to handle "insert break" key presses (i.e. Enter).
* *
* @return The action, or <code>null</code> if the default action should * @return The action, or <code>null</code> if the default action should be
* be used. * used.
*/ */
public Action getInsertBreakAction(); public Action getInsertBreakAction();
/** /**
* Returns whether tokens of the specified type should have "mark * Returns whether tokens of the specified type should have "mark occurrences"
* occurrences" enabled for the current programming language. * enabled for the current programming language.
* *
* @param type * @param type The token type.
* The token type. * @return Whether tokens of this type should have "mark occurrences" enabled.
* @return Whether tokens of this type should have "mark occurrences"
* enabled.
*/ */
public boolean getMarkOccurrencesOfTokenType(int type); public boolean getMarkOccurrencesOfTokenType(int type);
/** /**
* Returns the object in charge of marking all occurrences of the token * Returns the object in charge of marking all occurrences of the token at the
* at the current caret position, if it is a relevant token. If * current caret position, if it is a relevant token. If <code>null</code> is
* <code>null</code> is returned, a default <code>OccurrenceMarker</code> * returned, a default <code>OccurrenceMarker</code> is used.
* is used.
* *
* @return The occurrence marker for this language, or <code>null</code> * @return The occurrence marker for this language, or <code>null</code> for
* for none. * none.
*/ */
public OccurrenceMarker getOccurrenceMarker(); public OccurrenceMarker getOccurrenceMarker();
/** /**
* If a line ends in the specified token, this method returns whether * If a line ends in the specified token, this method returns whether a new line
* a new line inserted after that line should be indented. * inserted after that line should be indented.
* *
* @param token * @param token The token the previous line ends with.
* The token the previous line ends with.
* @return Whether the next line should be indented. * @return Whether the next line should be indented.
*/ */
public boolean getShouldIndentNextLineAfter(Token token); public boolean getShouldIndentNextLineAfter(Token token);
/** /**
* Returns the first token in the linked list of tokens generated * Returns the first token in the linked list of tokens generated from
* from <code>text</code>. This method must be implemented by * <code>text</code>. This method must be implemented by subclasses so they can
* subclasses so they can correctly implement syntax highlighting. * correctly implement syntax highlighting.
* *
* @param text * @param text The text from which to get tokens.
* The text from which to get tokens. * @param initialTokenType The token type we should start with.
* @param initialTokenType * @param startOffset The offset into the document at which
* The token type we should start with. * <code>text</code> starts.
* @param startOffset * @return The first <code>Token</code> in a linked list representing the syntax
* The offset into the document at which * highlighted text.
* <code>text</code> starts.
* @return The first <code>Token</code> in a linked list representing
* the syntax highlighted text.
*/ */
public Token getTokenList(Segment text, int initialTokenType, int startOffset); public Token getTokenList(Segment text, int initialTokenType, int startOffset);
/** /**
* Returns whether a character could be part of an "identifier" token * Returns whether a character could be part of an "identifier" token in a
* in a specific language. This is used to identify such things as the * specific language. This is used to identify such things as the bounds of the
* bounds of the "word" to select on double-clicking. * "word" to select on double-clicking.
* *
* @param languageIndex * @param languageIndex The language index the character was found in.
* The language index the character was found in. * @param ch The character.
* @param ch
* The character.
* @return Whether the character could be part of an "identifier" token. * @return Whether the character could be part of an "identifier" token.
*/ */
public boolean isIdentifierChar(int languageIndex, char ch); public boolean isIdentifierChar(int languageIndex, char ch);
/** /**
* Returns whether this language is a markup language. * Returns whether this language is a markup language.
* *
@@ -16,7 +16,7 @@ import javax.swing.text.Segment;
* @version 1.0 * @version 1.0
*/ */
public abstract class TokenMakerBase implements TokenMaker { public abstract class TokenMakerBase implements TokenMaker {
/** /**
* The first token in the returned linked list. * The first token in the returned linked list.
*/ */
@@ -34,20 +34,18 @@ public abstract class TokenMakerBase implements TokenMaker {
*/ */
private TokenFactory tokenFactory; private TokenFactory tokenFactory;
/** /**
* Highlights occurrences of the current token in the editor, if it is * Highlights occurrences of the current token in the editor, if it is relevant.
* relevant.
*/ */
private OccurrenceMarker occurrenceMarker; private OccurrenceMarker occurrenceMarker;
/** /**
* "0" implies this is the "main" language being highlighted. Positive * "0" implies this is the "main" language being highlighted. Positive values
* values imply various "secondary" or "embedded" languages, such as CSS * imply various "secondary" or "embedded" languages, such as CSS or JavaScript
* or JavaScript in HTML. While this value is non-zero, tokens will be * in HTML. While this value is non-zero, tokens will be generated with this
* generated with this language index so they can (possibly) be painted * language index so they can (possibly) be painted differently, so "embedded"
* differently, so "embedded" languages can be rendered with a special * languages can be rendered with a special background.
* background.
*/ */
private int languageIndex; private int languageIndex;
/** /**
* Constructor. * Constructor.
*/ */
@@ -55,7 +53,7 @@ public abstract class TokenMakerBase implements TokenMaker {
firstToken = currentToken = previousToken = null; firstToken = currentToken = previousToken = null;
tokenFactory = new DefaultTokenFactory(); tokenFactory = new DefaultTokenFactory();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -72,26 +70,20 @@ public abstract class TokenMakerBase implements TokenMaker {
} }
currentToken.setLanguageIndex(languageIndex); currentToken.setLanguageIndex(languageIndex);
} }
/** /**
* Adds the token specified to the current linked list of tokens. * Adds the token specified to the current linked list of tokens.
* *
* @param segment * @param segment <code>Segment</code> to get text from.
* <code>Segment</code> to get text from. * @param start Start offset in <code>segment</code> of token.
* @param start * @param end End offset in <code>segment</code> of token.
* Start offset in <code>segment</code> of token. * @param tokenType The token's type.
* @param end * @param startOffset The offset in the document at which this token occurs.
* End offset in <code>segment</code> of token.
* @param tokenType
* The token's type.
* @param startOffset
* The offset in the document at which this token
* occurs.
*/ */
public void addToken(Segment segment, int start, int end, int tokenType, int startOffset) { public void addToken(Segment segment, int start, int end, int tokenType, int startOffset) {
addToken(segment.array, start, end, tokenType, startOffset); addToken(segment.array, start, end, tokenType, startOffset);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -99,23 +91,16 @@ public abstract class TokenMakerBase implements TokenMaker {
public void addToken(char[] array, int start, int end, int tokenType, int startOffset) { public void addToken(char[] array, int start, int end, int tokenType, int startOffset) {
addToken(array, start, end, tokenType, startOffset, false); addToken(array, start, end, tokenType, startOffset, false);
} }
/** /**
* Adds the token specified to the current linked list of tokens. * Adds the token specified to the current linked list of tokens.
* *
* @param array * @param array The character array.
* The character array. * @param start The starting offset in the array.
* @param start * @param end The ending offset in the array.
* The starting offset in the array. * @param tokenType The token's type.
* @param end * @param startOffset The offset in the document at which this token occurs.
* The ending offset in the array. * @param hyperlink Whether this token is a hyperlink.
* @param tokenType
* The token's type.
* @param startOffset
* The offset in the document at which this token
* occurs.
* @param hyperlink
* Whether this token is a hyperlink.
*/ */
public void addToken(char[] array, int start, int end, int tokenType, int startOffset, boolean hyperlink) { public void addToken(char[] array, int start, int end, int tokenType, int startOffset, boolean hyperlink) {
if (firstToken == null) { if (firstToken == null) {
@@ -130,59 +115,56 @@ public abstract class TokenMakerBase implements TokenMaker {
currentToken.setLanguageIndex(languageIndex); currentToken.setLanguageIndex(languageIndex);
currentToken.setHyperlink(hyperlink); currentToken.setHyperlink(hyperlink);
} }
/** /**
* Returns the occurrence marker to use for this token maker. Subclasses * Returns the occurrence marker to use for this token maker. Subclasses can
* can override to use different implementations. * override to use different implementations.
* *
* @return The occurrence marker to use. * @return The occurrence marker to use.
*/ */
protected OccurrenceMarker createOccurrenceMarker() { protected OccurrenceMarker createOccurrenceMarker() {
return new DefaultOccurrenceMarker(); return new DefaultOccurrenceMarker();
} }
/** /**
* Returns the closest {@link TokenTypes "standard" token type} for a given * Returns the closest {@link TokenTypes "standard" token type} for a given
* "internal" token type (e.g. one whose value is <code>&lt; 0</code>). * "internal" token type (e.g. one whose value is <code>&lt; 0</code>).
* <p> * <p>
* *
* The default implementation returns <code>type</code> always, which * The default implementation returns <code>type</code> always, which denotes
* denotes that a mapping from internal token types to standard token types * that a mapping from internal token types to standard token types is not
* is not defined; subclasses can override. * defined; subclasses can override.
* *
* @param type * @param type The token type.
* The token type.
* @return The closest "standard" token type. * @return The closest "standard" token type.
*/ */
@Override @Override
public int getClosestStandardTokenTypeForInternalType(int type) { public int getClosestStandardTokenTypeForInternalType(int type) {
return type; return type;
} }
/** /**
* Returns whether this programming language uses curly braces * Returns whether this programming language uses curly braces ('<code>{</code>'
* ('<code>{</code>' and '<code>}</code>') to denote code blocks. * and '<code>}</code>') to denote code blocks.
* *
* The default implementation returns <code>false</code>; subclasses can * The default implementation returns <code>false</code>; subclasses can
* override this method if necessary. * override this method if necessary.
* *
* @param languageIndex * @param languageIndex The language index at the offset in question. Since some
* The language index at the offset in question. * <code>TokenMaker</code>s effectively have nested
* Since some <code>TokenMaker</code>s effectively have nested * languages (such as JavaScript in HTML), this parameter
* languages (such as JavaScript in HTML), this parameter tells * tells the <code>TokenMaker</code> what sub-language to
* the * look at.
* <code>TokenMaker</code> what sub-language to look at.
* @return Whether curly braces denote code blocks. * @return Whether curly braces denote code blocks.
*/ */
@Override @Override
public boolean getCurlyBracesDenoteCodeBlocks(int languageIndex) { public boolean getCurlyBracesDenoteCodeBlocks(int languageIndex) {
return false; return false;
} }
/** /**
* Returns an action to handle "insert break" key presses (i.e. Enter). * Returns an action to handle "insert break" key presses (i.e. Enter). The
* The default implementation returns <code>null</code>. Subclasses * default implementation returns <code>null</code>. Subclasses can override.
* can override.
* *
* @return The default implementation always returns <code>null</code>. * @return The default implementation always returns <code>null</code>.
*/ */
@@ -190,7 +172,7 @@ public abstract class TokenMakerBase implements TokenMaker {
public Action getInsertBreakAction() { public Action getInsertBreakAction() {
return null; return null;
} }
/** /**
* Returns the current language index. * Returns the current language index.
* *
@@ -200,7 +182,7 @@ public abstract class TokenMakerBase implements TokenMaker {
protected int getLanguageIndex() { protected int getLanguageIndex() {
return languageIndex; return languageIndex;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -213,7 +195,7 @@ public abstract class TokenMakerBase implements TokenMaker {
} }
return t.getType(); return t.getType();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -221,24 +203,22 @@ public abstract class TokenMakerBase implements TokenMaker {
public String[] getLineCommentStartAndEnd(int languageIndex) { public String[] getLineCommentStartAndEnd(int languageIndex) {
return null; return null;
} }
/** /**
* Returns whether tokens of the specified type should have "mark * Returns whether tokens of the specified type should have "mark occurrences"
* occurrences" enabled for the current programming language. The default * enabled for the current programming language. The default implementation
* implementation returns true if <tt>type</tt> is {@link Token#IDENTIFIER}. * returns true if <tt>type</tt> is {@link Token#IDENTIFIER}. Subclasses can
* Subclasses can override this method to support other token types, such * override this method to support other token types, such as
* as {@link Token#VARIABLE}. * {@link Token#VARIABLE}.
* *
* @param type * @param type The token type.
* The token type. * @return Whether tokens of this type should have "mark occurrences" enabled.
* @return Whether tokens of this type should have "mark occurrences"
* enabled.
*/ */
@Override @Override
public boolean getMarkOccurrencesOfTokenType(int type) { public boolean getMarkOccurrencesOfTokenType(int type) {
return type == Token.IDENTIFIER; return type == Token.IDENTIFIER;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -249,34 +229,33 @@ public abstract class TokenMakerBase implements TokenMaker {
} }
return occurrenceMarker; return occurrenceMarker;
} }
/** /**
* The default implementation returns <code>false</code> always. Languages * The default implementation returns <code>false</code> always. Languages that
* that wish to better support auto-indentation can override this method. * wish to better support auto-indentation can override this method.
* *
* @param token * @param token The token the previous line ends with.
* The token the previous line ends with.
* @return Whether the next line should be indented. * @return Whether the next line should be indented.
*/ */
@Override @Override
public boolean getShouldIndentNextLineAfter(Token token) { public boolean getShouldIndentNextLineAfter(Token token) {
return false; return false;
} }
/** /**
* Returns whether a character could be part of an "identifier" token * Returns whether a character could be part of an "identifier" token in a
* in a specific language. The default implementation returns * specific language. The default implementation returns <code>true</code> for
* <code>true</code> for letters, numbers, and certain symbols. * letters, numbers, and certain symbols.
*/ */
@Override @Override
public boolean isIdentifierChar(int languageIndex, char ch) { public boolean isIdentifierChar(int languageIndex, char ch) {
return Character.isLetterOrDigit(ch) || ch == '_' || ch == '$'; return Character.isLetterOrDigit(ch) || ch == '_' || ch == '$';
} }
/** /**
* The default implementation returns <code>false</code> always. * The default implementation returns <code>false</code> always. Subclasses that
* Subclasses that are highlighting a markup language should override this * are highlighting a markup language should override this method to return
* method to return <code>true</code>. * <code>true</code>.
* *
* @return <code>false</code> always. * @return <code>false</code> always.
*/ */
@@ -284,29 +263,27 @@ public abstract class TokenMakerBase implements TokenMaker {
public boolean isMarkupLanguage() { public boolean isMarkupLanguage() {
return false; return false;
} }
/** /**
* Deletes the linked list of tokens so we can begin anew. This should * Deletes the linked list of tokens so we can begin anew. This should never
* never have to be called by the programmer, as it is automatically * have to be called by the programmer, as it is automatically called whenever
* called whenever the user calls * the user calls {@link #getLastTokenTypeOnLine(Segment, int)} or
* {@link #getLastTokenTypeOnLine(Segment, int)} or
* {@link #getTokenList(Segment, int, int)}. * {@link #getTokenList(Segment, int, int)}.
*/ */
protected void resetTokenList() { protected void resetTokenList() {
firstToken = currentToken = previousToken = null; firstToken = currentToken = previousToken = null;
tokenFactory.resetAllTokens(); tokenFactory.resetAllTokens();
} }
/** /**
* Sets the language index to assign to tokens moving forward. This * Sets the language index to assign to tokens moving forward. This property is
* property is used to designate tokens as being in "secondary" languages * used to designate tokens as being in "secondary" languages (such as CSS or
* (such as CSS or JavaScript in HTML). * JavaScript in HTML).
* *
* @param languageIndex * @param languageIndex The new language index. A value of <code>0</code>
* The new language index. A value of * denotes the "main" language, any positive value denotes
* <code>0</code> denotes the "main" language, any positive value * a specific secondary language. Negative values will be
* denotes a specific secondary language. Negative values will * treated as <code>0</code>.
* be treated as <code>0</code>.
* @see #getLanguageIndex() * @see #getLanguageIndex()
*/ */
protected void setLanguageIndex(int languageIndex) { protected void setLanguageIndex(int languageIndex) {
@@ -18,10 +18,9 @@ import org.fife.ui.rsyntaxtextarea.modes.PlainTextTokenMaker;
* @version 1.0 * @version 1.0
*/ */
public abstract class TokenMakerFactory { public abstract class TokenMakerFactory {
/** /**
* If this system property is set, a custom <code>TokenMakerFactory</code> * If this system property is set, a custom <code>TokenMakerFactory</code> of
* of
* the specified class will be used as the default token maker factory. * the specified class will be used as the default token maker factory.
*/ */
public static final String PROPERTY_DEFAULT_TOKEN_MAKER_FACTORY = "TokenMakerFactory"; public static final String PROPERTY_DEFAULT_TOKEN_MAKER_FACTORY = "TokenMakerFactory";
@@ -29,7 +28,7 @@ public abstract class TokenMakerFactory {
* The singleton default <code>TokenMakerFactory</code> instance. * The singleton default <code>TokenMakerFactory</code> instance.
*/ */
private static TokenMakerFactory DEFAULT_INSTANCE; private static TokenMakerFactory DEFAULT_INSTANCE;
/** /**
* Returns the default <code>TokenMakerFactory</code> instance. This is the * Returns the default <code>TokenMakerFactory</code> instance. This is the
* factory used by all {@link RSyntaxDocument}s by default. * factory used by all {@link RSyntaxDocument}s by default.
@@ -59,12 +58,11 @@ public abstract class TokenMakerFactory {
} }
return DEFAULT_INSTANCE; return DEFAULT_INSTANCE;
} }
/** /**
* Returns a {@link TokenMaker} for the specified key. * Returns a {@link TokenMaker} for the specified key.
* *
* @param key * @param key The key.
* The key.
* @return The corresponding <code>TokenMaker</code>, or * @return The corresponding <code>TokenMaker</code>, or
* {@link PlainTextTokenMaker} if none matches the specified key. * {@link PlainTextTokenMaker} if none matches the specified key.
*/ */
@@ -75,36 +73,31 @@ public abstract class TokenMakerFactory {
} }
return tm; return tm;
} }
/** /**
* Returns a {@link TokenMaker} for the specified key. * Returns a {@link TokenMaker} for the specified key.
* *
* @param key * @param key The key.
* The key. * @return The corresponding <code>TokenMaker</code>, or <code>null</code> if
* @return The corresponding <code>TokenMaker</code>, or <code>null</code>
* if
* none matches the specified key. * none matches the specified key.
*/ */
protected abstract TokenMaker getTokenMakerImpl(String key); protected abstract TokenMaker getTokenMakerImpl(String key);
/** /**
* Returns the set of keys that this factory maps to token makers. * Returns the set of keys that this factory maps to token makers.
* *
* @return The set of keys. * @return The set of keys.
*/ */
public abstract Set<String> keySet(); public abstract Set<String> keySet();
/** /**
* Sets the default <code>TokenMakerFactory</code> instance. This is the * Sets the default <code>TokenMakerFactory</code> instance. This is the factory
* factory
* used by all future {@link RSyntaxDocument}s by default. * used by all future {@link RSyntaxDocument}s by default.
* <code>RSyntaxDocument</code>s that have already been created are not * <code>RSyntaxDocument</code>s that have already been created are not
* affected. * affected.
* *
* @param tmf * @param tmf The factory.
* The factory. * @throws IllegalArgumentException If <code>tmf</code> is <code>null</code>.
* @throws IllegalArgumentException
* If <code>tmf</code> is <code>null</code>.
* @see #getDefaultInstance() * @see #getDefaultInstance()
*/ */
public static synchronized void setDefaultInstance(TokenMakerFactory tmf) { public static synchronized void setDefaultInstance(TokenMakerFactory tmf) {
+65 -85
View File
@@ -10,8 +10,8 @@ package org.fife.ui.rsyntaxtextarea;
import javax.swing.text.Segment; import javax.swing.text.Segment;
/** /**
* A hash table for reserved words, etc. defined by a {@link TokenMaker}. * A hash table for reserved words, etc. defined by a {@link TokenMaker}. This
* This class is designed for the quick lookup of tokens, as it can compare * class is designed for the quick lookup of tokens, as it can compare
* <code>Segment</code>s without the need to allocate a new string. * <code>Segment</code>s without the need to allocate a new string.
* <p> * <p>
* *
@@ -27,98 +27,86 @@ import javax.swing.text.Segment;
* @version 0.6 * @version 0.6
*/ */
public class TokenMap { public class TokenMap {
private int size; private int size;
private TokenMapToken[] tokenMap; private TokenMapToken[] tokenMap;
private boolean ignoreCase; private boolean ignoreCase;
private static final int DEFAULT_TOKEN_MAP_SIZE = 52; private static final int DEFAULT_TOKEN_MAP_SIZE = 52;
/** /**
* Constructs a new token map that is case-sensitive. * Constructs a new token map that is case-sensitive.
*/ */
public TokenMap() { public TokenMap() {
this(DEFAULT_TOKEN_MAP_SIZE); this(DEFAULT_TOKEN_MAP_SIZE);
} }
/** /**
* Constructs a new token map that is case-sensitive. * Constructs a new token map that is case-sensitive.
* *
* @param size * @param size The size of the token map.
* The size of the token map.
*/ */
public TokenMap(int size) { public TokenMap(int size) {
this(size, false); this(size, false);
} }
/** /**
* Constructs a new token map. * Constructs a new token map.
* *
* @param ignoreCase * @param ignoreCase Whether or not this token map should ignore case when
* Whether or not this token map should ignore case * comparing tokens.
* when comparing tokens.
*/ */
public TokenMap(boolean ignoreCase) { public TokenMap(boolean ignoreCase) {
this(DEFAULT_TOKEN_MAP_SIZE, ignoreCase); this(DEFAULT_TOKEN_MAP_SIZE, ignoreCase);
} }
/** /**
* Constructs a new token map. * Constructs a new token map.
* *
* @param size * @param size The size of the token map.
* The size of the token map. * @param ignoreCase Whether or not this token map should ignore case when
* @param ignoreCase * comparing tokens.
* Whether or not this token map should ignore case
* when comparing tokens.
*/ */
public TokenMap(int size, boolean ignoreCase) { public TokenMap(int size, boolean ignoreCase) {
this.size = size; this.size = size;
tokenMap = new TokenMapToken[size]; tokenMap = new TokenMapToken[size];
this.ignoreCase = ignoreCase; this.ignoreCase = ignoreCase;
} }
/** /**
* Adds a token to a specified bucket in the token map. * Adds a token to a specified bucket in the token map.
* *
* @param bucket * @param bucket The bucket in which to add the token.
* The bucket in which to add the token. * @param token The token to add.
* @param token
* The token to add.
*/ */
private void addTokenToBucket(int bucket, TokenMapToken token) { private void addTokenToBucket(int bucket, TokenMapToken token) {
TokenMapToken old = tokenMap[bucket]; TokenMapToken old = tokenMap[bucket];
token.nextToken = old; token.nextToken = old;
tokenMap[bucket] = token; tokenMap[bucket] = token;
} }
/** /**
* Returns the token type associated with the given text, if the given * Returns the token type associated with the given text, if the given text is
* text is in this token map. If it isn't, <code>-1</code> is returned. * in this token map. If it isn't, <code>-1</code> is returned.
* *
* @param text * @param text The segment from which to get the text to compare.
* The segment from which to get the text to compare. * @param start The starting index in the segment of the text.
* @param start * @param end The ending index in the segment of the text.
* The starting index in the segment of the text. * @return The token type associated with the given text, or <code>-1</code> if
* @param end * this token was not specified in this map.
* The ending index in the segment of the text.
* @return The token type associated with the given text, or
* <code>-1</code> if this token was not specified in this map.
*/ */
public int get(Segment text, int start, int end) { public int get(Segment text, int start, int end) {
return get(text.array, start, end); return get(text.array, start, end);
} }
/** /**
* Returns the token type associated with the given text, if the given * Returns the token type associated with the given text, if the given text is
* text is in this token map. If it isn't, <code>-1</code> is returned. * in this token map. If it isn't, <code>-1</code> is returned.
* *
* @param array1 * @param array1 An array of characters containing the text.
* An array of characters containing the text. * @param start The starting index in the array of the text.
* @param start * @param end The ending index in the array of the text.
* The starting index in the array of the text. * @return The token type associated with the given text, or <code>-1</code> if
* @param end * this token was not specified in this map.
* The ending index in the array of the text.
* @return The token type associated with the given text, or
* <code>-1</code> if this token was not specified in this map.
*/ */
public int get(char[] array1, int start, int end) { public int get(char[] array1, int start, int end) {
int length1 = end - start + 1; int length1 = end - start + 1;
@@ -129,14 +117,13 @@ public class TokenMap {
int offset1; int offset1;
int length; int length;
/* /*
* We check whether or not to ignore case before doing any looping to * We check whether or not to ignore case before doing any looping to minimize
* minimize the number of extraneous comparisons we do. This makes * the number of extraneous comparisons we do. This makes for slightly redundant
* for slightly redundant code, but it'll be a little more efficient. * code, but it'll be a little more efficient.
*/ */
// If matches are case-sensitive (C, C++, Java, etc.)... // If matches are case-sensitive (C, C++, Java, etc.)...
if (!ignoreCase) { if (!ignoreCase) {
mainLoop: mainLoop: while (token != null) {
while (token != null) {
if (token.length == length1) { if (token.length == length1) {
array2 = token.text; array2 = token.text;
offset2 = token.offset; offset2 = token.offset;
@@ -157,8 +144,7 @@ public class TokenMap {
// Note that all tokens saved in this map were converted to // Note that all tokens saved in this map were converted to
// lower-case already. // lower-case already.
else { else {
mainLoop2: mainLoop2: while (token != null) {
while (token != null) {
if (token.length == length1) { if (token.length == length1) {
array2 = token.text; array2 = token.text;
offset2 = token.offset; offset2 = token.offset;
@@ -178,40 +164,36 @@ public class TokenMap {
// Didn't match any of the tokens in the bucket. // Didn't match any of the tokens in the bucket.
return -1; return -1;
} }
/** /**
* Returns the hash code for a given string. * Returns the hash code for a given string.
* *
* @param text * @param text The text to hash.
* The text to hash. * @param offset The offset into the text at which to start hashing.
* @param offset * @param length The last character in the text to hash.
* The offset into the text at which to start hashing.
* @param length
* The last character in the text to hash.
* @return The hash code. * @return The hash code.
*/ */
private int getHashCode(char[] text, int offset, int length) { private int getHashCode(char[] text, int offset, int length) {
return (RSyntaxUtilities.toLowerCase(text[offset]) + RSyntaxUtilities.toLowerCase(text[offset + length - 1])) % size; return (RSyntaxUtilities.toLowerCase(text[offset]) + RSyntaxUtilities.toLowerCase(text[offset + length - 1]))
% size;
} }
/** /**
* Returns whether this token map ignores case when checking for tokens. * Returns whether this token map ignores case when checking for tokens. This
* This property is set in the constructor and cannot be changed, as this * property is set in the constructor and cannot be changed, as this is an
* is an intrinsic property of a particular programming language. * intrinsic property of a particular programming language.
* *
* @return Whether or not this token maker is ignoring case. * @return Whether or not this token maker is ignoring case.
*/ */
protected boolean isIgnoringCase() { protected boolean isIgnoringCase() {
return ignoreCase; return ignoreCase;
} }
/** /**
* Adds a string to this token map. * Adds a string to this token map.
* *
* @param string * @param string The string to add.
* The string to add. * @param tokenType The type of token the string is.
* @param tokenType
* The type of token the string is.
*/ */
public void put(final String string, final int tokenType) { public void put(final String string, final int tokenType) {
if (isIgnoringCase()) { if (isIgnoringCase()) {
@@ -220,44 +202,42 @@ public class TokenMap {
put(string.toCharArray(), tokenType); put(string.toCharArray(), tokenType);
} }
} }
/** /**
* Adds a string to this token map. The char array passed-in will be used * Adds a string to this token map. The char array passed-in will be used as the
* as the actual data for the token, so it may well be modified (such as * actual data for the token, so it may well be modified (such as lower-casing
* lower-casing it if <code>ignoreCase</code> is <code>true</code>). This * it if <code>ignoreCase</code> is <code>true</code>). This shouldn't be an
* shouldn't be an issue though as this method is only called from the * issue though as this method is only called from the public <code>put</code>
* public <code>put</code> method, which allocates a new char array. * method, which allocates a new char array.
* *
* @param string * @param string The string to add.
* The string to add. * @param tokenType The type of token the string is.
* @param tokenType
* The type of token the string is.
*/ */
private void put(char[] string, int tokenType) { private void put(char[] string, int tokenType) {
int hashCode = getHashCode(string, 0, string.length); int hashCode = getHashCode(string, 0, string.length);
addTokenToBucket(hashCode, new TokenMapToken(string, tokenType)); addTokenToBucket(hashCode, new TokenMapToken(string, tokenType));
} }
/** /**
* The "token" used by a token map. Note that this isn't the same thing * The "token" used by a token map. Note that this isn't the same thing as the
* as the {@link Token} class, but it's basically a 1-1 correspondence * {@link Token} class, but it's basically a 1-1 correspondence for reserved
* for reserved words, etc. * words, etc.
*/ */
private static final class TokenMapToken { private static final class TokenMapToken {
private char[] text; private char[] text;
private int offset; private int offset;
private int length; private int length;
private int tokenType; private int tokenType;
private TokenMapToken nextToken; private TokenMapToken nextToken;
private TokenMapToken(char[] text, int tokenType) { private TokenMapToken(char[] text, int tokenType) {
this.text = text; this.text = text;
this.offset = 0; this.offset = 0;
this.length = text.length; this.length = text.length;
this.tokenType = tokenType; this.tokenType = tokenType;
} }
@Override @Override
public String toString() { public String toString() {
return "[TokenMapToken: " + new String(text, offset, length) + "]"; return "[TokenMapToken: " + new String(text, offset, length) + "]";
@@ -22,36 +22,32 @@ package org.fife.ui.rsyntaxtextarea;
* @version 0.1 * @version 0.1
*/ */
public interface TokenOrientedView { public interface TokenOrientedView {
/** /**
* Returns a token list for the <i>physical</i> line above the physical * Returns a token list for the <i>physical</i> line above the physical line
* line containing the specified offset into the document. Note that for * containing the specified offset into the document. Note that for a plain
* a plain (non-wrapped) view, this is simply the token list for the * (non-wrapped) view, this is simply the token list for the logical line above
* logical line above the line containing <code>offset</code>, since lines * the line containing <code>offset</code>, since lines are not wrapped. For a
* are not wrapped. For a wrapped view, this may or may not be tokens from * wrapped view, this may or may not be tokens from the same line.
* the same line.
* *
* @param offset * @param offset The offset in question.
* The offset in question. * @return A token list for the physical (and in this view, logical) line before
* @return A token list for the physical (and in this view, logical) line * this one. If no physical line is above the one containing
* before this one. If no physical line is above the one * <code>offset</code>, <code>null</code> is returned.
* containing <code>offset</code>, <code>null</code> is returned.
*/ */
Token getTokenListForPhysicalLineAbove(int offset); Token getTokenListForPhysicalLineAbove(int offset);
/** /**
* Returns a token list for the <i>physical</i> line below the physical * Returns a token list for the <i>physical</i> line below the physical line
* line containing the specified offset into the document. Note that for * containing the specified offset into the document. Note that for a plain
* a plain (non-wrapped) view, this is simply the token list for the * (non-wrapped) view, this is simply the token list for the logical line below
* logical line below the line containing <code>offset</code>, since lines * the line containing <code>offset</code>, since lines are not wrapped. For a
* are not wrapped. For a wrapped view, this may or may not be tokens from * wrapped view, this may or may not be tokens from the same line.
* the same line.
* *
* @param offset * @param offset The offset in question.
* The offset in question. * @return A token list for the physical (and in this view, logical) line after
* @return A token list for the physical (and in this view, logical) line * this one. If no physical line is after the one containing
* after this one. If no physical line is after the one * <code>offset</code>, <code>null</code> is returned.
* containing <code>offset</code>, <code>null</code> is returned.
*/ */
Token getTokenListForPhysicalLineBelow(int offset); Token getTokenListForPhysicalLineBelow(int offset);
} }
@@ -11,129 +11,99 @@ import java.awt.Graphics2D;
import javax.swing.text.TabExpander; import javax.swing.text.TabExpander;
/** /**
* Renders tokens in an instance of {@link RSyntaxTextArea}. One instance * Renders tokens in an instance of {@link RSyntaxTextArea}. One instance may
* may render tokens "regularly," another may render visible whitespace, for * render tokens "regularly," another may render visible whitespace, for
* example. * example.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
interface TokenPainter { interface TokenPainter {
/** /**
* Paints this token. * Paints this token.
* *
* @param token * @param token The token to render.
* The token to render. * @param g The graphics context in which to paint.
* @param g * @param x The x-coordinate at which to paint.
* The graphics context in which to paint. * @param y The y-coordinate at which to paint.
* @param x * @param host The text area this token is in.
* The x-coordinate at which to paint. * @param e How to expand tabs.
* @param y
* The y-coordinate at which to paint.
* @param host
* The text area this token is in.
* @param e
* How to expand tabs.
* @return The x-coordinate representing the end of the painted text. * @return The x-coordinate representing the end of the painted text.
*/ */
float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e); float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e);
/** /**
* Paints this token. * Paints this token.
* *
* @param token * @param token The token to render.
* The token to render. * @param g The graphics context in which to paint.
* @param g * @param x The x-coordinate at which to paint.
* The graphics context in which to paint. * @param y The y-coordinate at which to paint.
* @param x * @param host The text area this token is in.
* The x-coordinate at which to paint. * @param e How to expand tabs.
* @param y * @param clipStart The left boundary of the clip rectangle in which we're
* The y-coordinate at which to paint. * painting. This optimizes painting by allowing us to not
* @param host * paint paint when this token is "to the left" of the clip
* The text area this token is in. * rectangle.
* @param e
* How to expand tabs.
* @param clipStart
* The left boundary of the clip rectangle in which we're
* painting. This optimizes painting by allowing us to not paint
* paint when this token is "to the left" of the clip rectangle.
* @return The x-coordinate representing the end of the painted text. * @return The x-coordinate representing the end of the painted text.
*/ */
float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart); float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart);
/** /**
* Paints this token. * Paints this token.
* *
* @param token * @param token The token to render.
* The token to render. * @param g The graphics context in which to paint.
* @param g * @param x The x-coordinate at which to paint.
* The graphics context in which to paint. * @param y The y-coordinate at which to paint.
* @param x * @param host The text area this token is in.
* The x-coordinate at which to paint. * @param e How to expand tabs.
* @param y * @param clipStart The left boundary of the clip rectangle in which we're
* The y-coordinate at which to paint. * painting. This optimizes painting by allowing us to not
* @param host * paint paint when this token is "to the left" of the clip
* The text area this token is in. * rectangle.
* @param e * @param paintBG Whether to paint the background.
* How to expand tabs.
* @param clipStart
* The left boundary of the clip rectangle in which we're
* painting. This optimizes painting by allowing us to not paint
* paint when this token is "to the left" of the clip rectangle.
* @param paintBG
* Whether to paint the background.
* @return The x-coordinate representing the end of the painted text. * @return The x-coordinate representing the end of the painted text.
*/ */
float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart, boolean paintBG); float paint(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart,
boolean paintBG);
/** /**
* Paints this token as it should appear in a selected region of text * Paints this token as it should appear in a selected region of text (assuming
* (assuming painting with a selection-foreground color is enabled in the * painting with a selection-foreground color is enabled in the parent
* parent <code>RSyntaxTextArea</code>). * <code>RSyntaxTextArea</code>).
* *
* @param token * @param token The token to render.
* The token to render. * @param g The graphics context in which to paint.
* @param g * @param x The x-coordinate at which to paint.
* The graphics context in which to paint. * @param y The y-coordinate at which to paint.
* @param x * @param host The text area this token is in.
* The x-coordinate at which to paint. * @param e How to expand tabs.
* @param y * @param useSTC Whether to use the text area's "selected text color."
* The y-coordinate at which to paint.
* @param host
* The text area this token is in.
* @param e
* How to expand tabs.
* @param useSTC
* Whether to use the text area's "selected text color."
* @return The x-coordinate representing the end of the painted text. * @return The x-coordinate representing the end of the painted text.
*/ */
float paintSelected(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, boolean useSTC); float paintSelected(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e,
boolean useSTC);
/** /**
* Paints this token as it should appear in a selected region of text * Paints this token as it should appear in a selected region of text (assuming
* (assuming painting with a selection-foreground color is enabled in the * painting with a selection-foreground color is enabled in the parent
* parent <code>RSyntaxTextArea</code>). * <code>RSyntaxTextArea</code>).
* *
* @param token * @param token The token to render.
* The token to render. * @param g The graphics context in which to paint.
* @param g * @param x The x-coordinate at which to paint.
* The graphics context in which to paint. * @param y The y-coordinate at which to paint.
* @param x * @param host The text area this token is in.
* The x-coordinate at which to paint. * @param e How to expand tabs.
* @param y * @param clipStart The left boundary of the clip rectangle in which we're
* The y-coordinate at which to paint. * painting. This optimizes painting by allowing us to not
* @param host * paint paint when this token is "to the left" of the clip
* The text area this token is in. * rectangle.
* @param e * @param useSTC Whether to use the text area's "selected text color."
* How to expand tabs.
* @param clipStart
* The left boundary of the clip rectangle in which we're
* painting. This optimizes painting by allowing us to not paint
* paint when this token is "to the left" of the clip rectangle.
* @param useSTC
* Whether to use the text area's "selected text color."
* @return The x-coordinate representing the end of the painted text. * @return The x-coordinate representing the end of the painted text.
*/ */
float paintSelected(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart, boolean useSTC); float paintSelected(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e,
float clipStart, boolean useSTC);
} }
@@ -11,17 +11,17 @@ package org.fife.ui.rsyntaxtextarea;
* <p> * <p>
* *
* Note that all valid token types are &gt;= 0, so extensions of the TokenMaker * Note that all valid token types are &gt;= 0, so extensions of the TokenMaker
* class are free to internally use all ints &lt; 0 ONLY for "end-of-line" * class are free to internally use all ints &lt; 0 ONLY for "end-of-line" style
* style markers; they are ignored by painting implementations. * markers; they are ignored by painting implementations.
* *
* @author Robert Futrell * @author Robert Futrell
* @version 1.0 * @version 1.0
*/ */
public interface TokenTypes { public interface TokenTypes {
/** /**
* Tokens of type <code>NULL</code> mark the end of lines with no * Tokens of type <code>NULL</code> mark the end of lines with no multi-line
* multi-line token at the end (such as a block comment in C++). * token at the end (such as a block comment in C++).
*/ */
int NULL = 0; int NULL = 0;
int COMMENT_EOL = 1; int COMMENT_EOL = 1;
@@ -18,7 +18,7 @@ import java.net.URL;
* @version 1.0 * @version 1.0
*/ */
class URLFileLocation extends FileLocation { class URLFileLocation extends FileLocation {
/** /**
* URL of the remote file. * URL of the remote file.
*/ */
@@ -32,22 +32,21 @@ class URLFileLocation extends FileLocation {
* removed). * removed).
*/ */
private String fileName; private String fileName;
/** /**
* Constructor. * Constructor.
* *
* @param url * @param url The URL of the file.
* The URL of the file.
*/ */
URLFileLocation(URL url) { URLFileLocation(URL url) {
this.url = url; this.url = url;
fileFullPath = createFileFullPath(); fileFullPath = createFileFullPath();
fileName = createFileName(); fileName = createFileName();
} }
/** /**
* Creates a "prettied-up" URL to use. This will be stripped of * Creates a "prettied-up" URL to use. This will be stripped of sensitive
* sensitive information such as passwords. * information such as passwords.
* *
* @return The full path to use. * @return The full path to use.
*/ */
@@ -56,7 +55,7 @@ class URLFileLocation extends FileLocation {
fullPath = fullPath.replaceFirst("://([^:]+)(?:.+)@", "://$1@"); fullPath = fullPath.replaceFirst("://([^:]+)(?:.+)@", "://$1@");
return fullPath; return fullPath;
} }
/** /**
* Creates the "prettied-up" filename to use. * Creates the "prettied-up" filename to use.
* *
@@ -71,11 +70,11 @@ class URLFileLocation extends FileLocation {
} }
return fileName; return fileName;
} }
/** /**
* Returns the last time this file was modified, or * Returns the last time this file was modified, or
* {@link TextEditorPane#LAST_MODIFIED_UNKNOWN} if this value cannot be * {@link TextEditorPane#LAST_MODIFIED_UNKNOWN} if this value cannot be computed
* computed (such as for a remote file). * (such as for a remote file).
* *
* @return The last time this file was modified. This will always be * @return The last time this file was modified. This will always be
* {@link TextEditorPane#LAST_MODIFIED_UNKNOWN} for URL's. * {@link TextEditorPane#LAST_MODIFIED_UNKNOWN} for URL's.
@@ -84,7 +83,7 @@ class URLFileLocation extends FileLocation {
protected long getActualLastModified() { protected long getActualLastModified() {
return TextEditorPane.LAST_MODIFIED_UNKNOWN; return TextEditorPane.LAST_MODIFIED_UNKNOWN;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -92,7 +91,7 @@ class URLFileLocation extends FileLocation {
public String getFileFullPath() { public String getFileFullPath() {
return fileFullPath; return fileFullPath;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -100,7 +99,7 @@ class URLFileLocation extends FileLocation {
public String getFileName() { public String getFileName() {
return fileName; return fileName;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -108,7 +107,7 @@ class URLFileLocation extends FileLocation {
protected InputStream getInputStream() throws IOException { protected InputStream getInputStream() throws IOException {
return url.openStream(); return url.openStream();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -116,7 +115,7 @@ class URLFileLocation extends FileLocation {
protected OutputStream getOutputStream() throws IOException { protected OutputStream getOutputStream() throws IOException {
return url.openConnection().getOutputStream(); return url.openConnection().getOutputStream();
} }
/** /**
* Returns whether this file location is a local file. * Returns whether this file location is a local file.
* *
@@ -127,11 +126,11 @@ class URLFileLocation extends FileLocation {
public boolean isLocal() { public boolean isLocal() {
return "file".equalsIgnoreCase(url.getProtocol()); return "file".equalsIgnoreCase(url.getProtocol());
} }
/** /**
* Returns whether this file location is a local file and already * Returns whether this file location is a local file and already exists. This
* exists. This method always returns <code>false</code> since we * method always returns <code>false</code> since we cannot check this value
* cannot check this value easily. * easily.
* *
* @return <code>false</code> always. * @return <code>false</code> always.
* @see #isLocal() * @see #isLocal()
@@ -20,13 +20,11 @@ import javax.swing.text.TabExpander;
* The current implementation paints as follows: * The current implementation paints as follows:
* <ul> * <ul>
* <li>The first tab or space, if any, is found in the token.</li> * <li>The first tab or space, if any, is found in the token.</li>
* <li>If a tab was found, all characters up to it are painted as a * <li>If a tab was found, all characters up to it are painted as a group.</li>
* group.</li> * <li>If a space was found, all characters up to and including it are painted
* <li>If a space was found, all characters up to and including it are * (it is painted with a special symbol to denote it as a space).</li>
* painted (it is painted with a special symbol to denote it as * <li>If neither a tab nor a whitespace was found, all characters in the token
* a space).</li> * are painted.</li>
* <li>If neither a tab nor a whitespace was found, all characters in the
* token are painted.</li>
* <li>Repeat until all characters are painted.</li> * <li>Repeat until all characters are painted.</li>
* </ul> * </ul>
* This means that rendering hints are applied to all groups of characters * This means that rendering hints are applied to all groups of characters
@@ -46,13 +44,13 @@ import javax.swing.text.TabExpander;
* @version 1.0 * @version 1.0
*/ */
class VisibleWhitespaceTokenPainter extends DefaultTokenPainter { class VisibleWhitespaceTokenPainter extends DefaultTokenPainter {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
protected float paintImpl(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart, protected float paintImpl(Token token, Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e,
boolean selected, boolean useSTC) { float clipStart, boolean selected, boolean useSTC) {
int origX = (int) x; int origX = (int) x;
int textOffs = token.getTextOffset(); int textOffs = token.getTextOffset();
char[] text = token.getTextArray(); char[] text = token.getTextArray();
@@ -68,65 +66,65 @@ class VisibleWhitespaceTokenPainter extends DefaultTokenPainter {
int height = fm.getHeight(); int height = fm.getHeight();
for (int i = textOffs; i < end; i++) { for (int i = textOffs; i < end; i++) {
switch (text[i]) { switch (text[i]) {
case '\t': case '\t':
// Fill in background. // Fill in background.
nextX = x + fm.charsWidth(text, flushIndex, flushLen); nextX = x + fm.charsWidth(text, flushIndex, flushLen);
float nextNextX = e.nextTabStop(nextX, 0); float nextNextX = e.nextTabStop(nextX, 0);
if (bg != null) { if (bg != null) {
paintBackground(x, y, nextNextX - x, height, g, ascent, host, bg); paintBackground(x, y, nextNextX - x, height, g, ascent, host, bg);
} }
g.setColor(fg); g.setColor(fg);
// Paint chars cached before the tab. // Paint chars cached before the tab.
if (flushLen > 0) { if (flushLen > 0) {
g.drawChars(text, flushIndex, flushLen, (int) x, (int) y); g.drawChars(text, flushIndex, flushLen, (int) x, (int) y);
flushLen = 0; flushLen = 0;
} }
flushIndex = i + 1; flushIndex = i + 1;
// Draw an arrow representing the tab. // Draw an arrow representing the tab.
int halfHeight = height / 2; int halfHeight = height / 2;
int quarterHeight = halfHeight / 2; int quarterHeight = halfHeight / 2;
int ymid = (int) y - ascent + halfHeight; int ymid = (int) y - ascent + halfHeight;
g.drawLine((int) nextX, ymid, (int) nextNextX, ymid); g.drawLine((int) nextX, ymid, (int) nextNextX, ymid);
g.drawLine((int) nextNextX, ymid, (int) nextNextX - 4, ymid - quarterHeight); g.drawLine((int) nextNextX, ymid, (int) nextNextX - 4, ymid - quarterHeight);
g.drawLine((int) nextNextX, ymid, (int) nextNextX - 4, ymid + quarterHeight); g.drawLine((int) nextNextX, ymid, (int) nextNextX - 4, ymid + quarterHeight);
x = nextNextX; x = nextNextX;
break; break;
case ' ': case ' ':
// NOTE: There is a little bit of a "fudge factor" // NOTE: There is a little bit of a "fudge factor"
// here when "smooth text" is enabled, as "width" // here when "smooth text" is enabled, as "width"
// below may well not be the width given to the space // below may well not be the width given to the space
// by fm.charsWidth() (it depends on how it places the // by fm.charsWidth() (it depends on how it places the
// space with respect to the preceding character). // space with respect to the preceding character).
// But, we assume the approximation is close enough for // But, we assume the approximation is close enough for
// our drawing a dot for the space. // our drawing a dot for the space.
// "flushLen+1" ensures text is aligned correctly (or, // "flushLen+1" ensures text is aligned correctly (or,
// aligned the same as in getWidth()). // aligned the same as in getWidth()).
nextX = x + fm.charsWidth(text, flushIndex, flushLen + 1); nextX = x + fm.charsWidth(text, flushIndex, flushLen + 1);
int width = fm.charWidth(' '); int width = fm.charWidth(' ');
// Paint background. // Paint background.
if (bg != null) { if (bg != null) {
paintBackground(x, y, nextX - x, height, g, ascent, host, bg); paintBackground(x, y, nextX - x, height, g, ascent, host, bg);
} }
g.setColor(fg); g.setColor(fg);
// Paint chars before space. // Paint chars before space.
if (flushLen > 0) { if (flushLen > 0) {
g.drawChars(text, flushIndex, flushLen, (int) x, (int) y); g.drawChars(text, flushIndex, flushLen, (int) x, (int) y);
flushLen = 0; flushLen = 0;
} }
// Paint a dot representing the space. // Paint a dot representing the space.
int dotX = (int) (nextX - width / 2f); // "2.0f" for int dotX = (int) (nextX - width / 2f); // "2.0f" for
// FindBugs // FindBugs
int dotY = (int) (y - ascent + height / 2f); // Ditto int dotY = (int) (y - ascent + height / 2f); // Ditto
g.drawLine(dotX, dotY, dotX, dotY); g.drawLine(dotX, dotY, dotX, dotY);
flushIndex = i + 1; flushIndex = i + 1;
x = nextX; x = nextX;
break; break;
case '\f': case '\f':
// ??? // ???
// fall-through for now. // fall-through for now.
default: default:
flushLen += 1; flushLen += 1;
break; break;
} }
} }
nextX = x + fm.charsWidth(text, flushIndex, flushLen); nextX = x + fm.charsWidth(text, flushIndex, flushLen);
@@ -43,7 +43,7 @@ import org.fife.ui.rtextarea.Gutter;
* @version 0.2 * @version 0.2
*/ */
public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView { public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView {
private boolean widthChanging; private boolean widthChanging;
private int tabBase; private int tabBase;
private int tabSize; private int tabSize;
@@ -67,17 +67,16 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
// */ // */
// private static final char[] eolMarker = { '.' }; // private static final char[] eolMarker = { '.' };
/** /**
* The width of this view cannot be below this amount, as if the width * The width of this view cannot be below this amount, as if the width is ever 0
* is ever 0 (really a bug), we'll go into an infinite loop. * (really a bug), we'll go into an infinite loop.
*/ */
private static final int MIN_WIDTH = 20; private static final int MIN_WIDTH = 20;
/** /**
* Creates a new WrappedSyntaxView. Lines will be wrapped * Creates a new WrappedSyntaxView. Lines will be wrapped on character
* on character boundaries. * boundaries.
* *
* @param elem * @param elem the element underlying the view
* the element underlying the view
*/ */
public WrappedSyntaxView(Element elem) { public WrappedSyntaxView(Element elem) {
super(elem, Y_AXIS); super(elem, Y_AXIS);
@@ -87,14 +86,12 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
tempRect = new Rectangle(); tempRect = new Rectangle();
lineCountTempToken = new TokenImpl(); lineCountTempToken = new TokenImpl();
} }
/** /**
* This is called by the nested wrapped line * This is called by the nested wrapped line views to determine the break
* views to determine the break location. This can * location. This can be reimplemented to alter the breaking behavior. It will
* be reimplemented to alter the breaking behavior. * either break at word or character boundaries depending upon the break
* It will either break at word or character boundaries * argument given at construction.
* depending upon the break argument given at
* construction.
*/ */
protected int calculateBreakPosition(int p0, Token tokenList, float x0) { protected int calculateBreakPosition(int p0, Token tokenList, float x0) {
// System.err.println("------ beginning calculateBreakPosition() // System.err.println("------ beginning calculateBreakPosition()
@@ -143,7 +140,7 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
// return p; // return p;
return p + 1; return p + 1;
} }
// private int getBreakLocation(Token t, FontMetrics fm, int x0, int x, // private int getBreakLocation(Token t, FontMetrics fm, int x0, int x,
// TabExpander e) { // TabExpander e) {
// Segment s = new Segment(); // Segment s = new Segment();
@@ -153,27 +150,24 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
// return t.offset + Utilities.getBreakLocation(s, fm, x0, x, e, t.offset); // return t.offset + Utilities.getBreakLocation(s, fm, x0, x, e, t.offset);
// } // }
/** /**
* Gives notification from the document that attributes were changed * Gives notification from the document that attributes were changed in a
* in a location that this view is responsible for. * location that this view is responsible for.
* *
* @param e * @param e the change information from the associated document
* the change information from the associated document * @param a the current allocation of the view
* @param a * @param f the factory to use to rebuild if the view has children
* the current allocation of the view
* @param f
* the factory to use to rebuild if the view has children
* @see View#changedUpdate * @see View#changedUpdate
*/ */
@Override @Override
public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) { public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) {
updateChildren(e, a); updateChildren(e, a);
} }
/** /**
* Sets the allocation rectangle for a given line's view, but sets the * Sets the allocation rectangle for a given line's view, but sets the y value
* y value to the passed-in value. This should be used instead of * to the passed-in value. This should be used instead of
* {@link #childAllocation(int, Rectangle)} since it allows you to account * {@link #childAllocation(int, Rectangle)} since it allows you to account for
* for hidden lines in collapsed fold regions. * hidden lines in collapsed fold regions.
* *
* @param line * @param line
* @param y * @param y
@@ -192,25 +186,20 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
alloc.y -= margin.top; alloc.y -= margin.top;
} }
} }
/** /**
* Draws a single view (i.e., a line of text for a wrapped view), * Draws a single view (i.e., a line of text for a wrapped view), wrapping the
* wrapping the text onto multiple lines if necessary. * text onto multiple lines if necessary.
* *
* @param painter * @param painter The painter to use to render tokens.
* The painter to use to render tokens. * @param g The graphics context in which to paint.
* @param g * @param r The rectangle in which to paint.
* The graphics context in which to paint. * @param view The <code>View</code> to paint.
* @param r * @param fontHeight The height of the font being used.
* The rectangle in which to paint. * @param y The y-coordinate at which to begin painting.
* @param view
* The <code>View</code> to paint.
* @param fontHeight
* The height of the font being used.
* @param y
* The y-coordinate at which to begin painting.
*/ */
protected void drawView(TokenPainter painter, Graphics2D g, Rectangle r, View view, int fontHeight, int y, int line) { protected void drawView(TokenPainter painter, Graphics2D g, Rectangle r, View view, int fontHeight, int y,
int line) {
float x = r.x; float x = r.x;
LayeredHighlighter h = (LayeredHighlighter) host.getHighlighter(); LayeredHighlighter h = (LayeredHighlighter) host.getHighlighter();
RSyntaxDocument document = (RSyntaxDocument) getDocument(); RSyntaxDocument document = (RSyntaxDocument) getDocument();
@@ -262,31 +251,23 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
g.drawString("\u00B6", x, (float) y - fontHeight); g.drawString("\u00B6", x, (float) y - fontHeight);
} }
} }
/** /**
* Draws a single view (i.e., a line of text for a wrapped view), wrapping * Draws a single view (i.e., a line of text for a wrapped view), wrapping the
* the text onto multiple lines if necessary. Any selected text is * text onto multiple lines if necessary. Any selected text is rendered with the
* rendered with the editor's "selected text" color. * editor's "selected text" color.
* *
* @param painter * @param painter The painter to use to render tokens.
* The painter to use to render tokens. * @param g The graphics context in which to paint.
* @param g * @param r The rectangle in which to paint.
* The graphics context in which to paint. * @param view The <code>View</code> to paint.
* @param r * @param fontHeight The height of the font being used.
* The rectangle in which to paint. * @param y The y-coordinate at which to begin painting.
* @param view * @param selStart The start of the selection.
* The <code>View</code> to paint. * @param selEnd The end of the selection.
* @param fontHeight
* The height of the font being used.
* @param y
* The y-coordinate at which to begin painting.
* @param selStart
* The start of the selection.
* @param selEnd
* The end of the selection.
*/ */
protected void drawViewWithSelection(TokenPainter painter, Graphics2D g, Rectangle r, View view, int fontHeight, int y, int selStart, protected void drawViewWithSelection(TokenPainter painter, Graphics2D g, Rectangle r, View view, int fontHeight,
int selEnd) { int y, int selStart, int selEnd) {
float x = r.x; float x = r.x;
boolean useSTC = host.getUseSelectedTextColor(); boolean useSTC = host.getUseSelectedTextColor();
LayeredHighlighter h = (LayeredHighlighter) host.getHighlighter(); LayeredHighlighter h = (LayeredHighlighter) host.getHighlighter();
@@ -363,7 +344,8 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
if (token != null && token.isPaintable() && token.getOffset() < p) { if (token != null && token.isPaintable() && token.getOffset() < p) {
int tokenOffset = token.getOffset(); int tokenOffset = token.getOffset();
Token orig = token; Token orig = token;
token = new TokenImpl(drawSeg, tokenOffset - start, p - 1 - start, tokenOffset, token.getType(), token.getLanguageIndex()); token = new TokenImpl(drawSeg, tokenOffset - start, p - 1 - start, tokenOffset, token.getType(),
token.getLanguageIndex());
token.setLanguageIndex(token.getLanguageIndex()); token.setLanguageIndex(token.getLanguageIndex());
// Selection starts in this token // Selection starts in this token
if (token.containsPosition(selStart)) { if (token.containsPosition(selStart)) {
@@ -422,19 +404,16 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
g.drawString("\u00B6", x, (float) y - fontHeight); g.drawString("\u00B6", x, (float) y - fontHeight);
} }
} }
/** /**
* Fetches the allocation for the given child view. * Fetches the allocation for the given child view.
* <p> * <p>
* Overridden to account for code folding. * Overridden to account for code folding.
* *
* @param index * @param index The index of the child, &gt;= 0 &amp;&amp;&lt; getViewCount().
* The index of the child, &gt;= 0 &amp;&amp;&lt; getViewCount(). * @param a The allocation to this view
* @param a * @return The allocation to the child; or <code>null</code> if <code>a</code>
* The allocation to this view * is <code>null</code>; or <code>null</code> if the layout is invalid
* @return The allocation to the child; or <code>null</code> if
* <code>a</code> is <code>null</code>; or <code>null</code> if the
* layout is invalid
*/ */
@Override @Override
public Shape getChildAllocation(int index, Shape a) { public Shape getChildAllocation(int index, Shape a) {
@@ -451,16 +430,14 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
return null; return null;
} }
/** /**
* Fetches the allocation for the given child view to render into. * Fetches the allocation for the given child view to render into.
* <p> * <p>
* Overridden to account for lines hidden by collapsed folded regions. * Overridden to account for lines hidden by collapsed folded regions.
* *
* @param line * @param line The index of the child, &gt;= 0 &amp;&amp;&lt; getViewCount()
* The index of the child, &gt;= 0 &amp;&amp;&lt; getViewCount() * @param a The allocation to this view
* @param a
* The allocation to this view
* @return The allocation to the child * @return The allocation to the child
*/ */
public Shape getChildAllocationImpl(int line, Shape a) { public Shape getChildAllocationImpl(int line, Shape a) {
@@ -480,21 +457,17 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
childAllocation2(line, y, alloc); childAllocation2(line, y, alloc);
return alloc; return alloc;
} }
/** /**
* Determines the maximum span for this view along an * Determines the maximum span for this view along an axis. This is implemented
* axis. This is implemented to provide the superclass * to provide the superclass behavior after first making sure that the current
* behavior after first making sure that the current font * font metrics are cached (for the nested lines which use the metrics to
* metrics are cached (for the nested lines which use * determine the height of the potentially wrapped lines).
* the metrics to determine the height of the potentially
* wrapped lines).
* *
* @param axis * @param axis may be either View.X_AXIS or View.Y_AXIS
* may be either View.X_AXIS or View.Y_AXIS * @return the span the view would like to be rendered into. Typically the view
* @return the span the view would like to be rendered into. * is told to render into the span that is returned, although there is
* Typically the view is told to render into the span * no guarantee. The parent may choose to resize or break the view.
* that is returned, although there is no guarantee.
* The parent may choose to resize or break the view.
* @see View#getMaximumSpan * @see View#getMaximumSpan
*/ */
@Override @Override
@@ -506,21 +479,17 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
return span; return span;
} }
/** /**
* Determines the minimum span for this view along an * Determines the minimum span for this view along an axis. This is implemented
* axis. This is implemented to provide the superclass * to provide the superclass behavior after first making sure that the current
* behavior after first making sure that the current font * font metrics are cached (for the nested lines which use the metrics to
* metrics are cached (for the nested lines which use * determine the height of the potentially wrapped lines).
* the metrics to determine the height of the potentially
* wrapped lines).
* *
* @param axis * @param axis may be either View.X_AXIS or View.Y_AXIS
* may be either View.X_AXIS or View.Y_AXIS * @return the span the view would like to be rendered into. Typically the view
* @return the span the view would like to be rendered into. * is told to render into the span that is returned, although there is
* Typically the view is told to render into the span * no guarantee. The parent may choose to resize or break the view.
* that is returned, although there is no guarantee.
* The parent may choose to resize or break the view.
* @see View#getMinimumSpan * @see View#getMinimumSpan
*/ */
@Override @Override
@@ -532,21 +501,17 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
return span; return span;
} }
/** /**
* Determines the preferred span for this view along an * Determines the preferred span for this view along an axis. This is
* axis. This is implemented to provide the superclass * implemented to provide the superclass behavior after first making sure that
* behavior after first making sure that the current font * the current font metrics are cached (for the nested lines which use the
* metrics are cached (for the nested lines which use * metrics to determine the height of the potentially wrapped lines).
* the metrics to determine the height of the potentially
* wrapped lines).
* *
* @param axis * @param axis may be either View.X_AXIS or View.Y_AXIS
* may be either View.X_AXIS or View.Y_AXIS * @return the span the view would like to be rendered into. Typically the view
* @return the span the view would like to be rendered into. * is told to render into the span that is returned, although there is
* Typically the view is told to render into the span * no guarantee. The parent may choose to resize or break the view.
* that is returned, although there is no guarantee.
* The parent may choose to resize or break the view.
* @see View#getPreferredSpan * @see View#getPreferredSpan
*/ */
@Override @Override
@@ -573,7 +538,7 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
return span; return span;
} }
/** /**
* Returns the tab size set for the document, defaulting to 5. * Returns the tab size set for the document, defaulting to 5.
* *
@@ -584,7 +549,7 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
int size = (i != null) ? i.intValue() : 5; int size = (i != null) ? i.intValue() : 5;
return size; return size;
} }
/** /**
* Overridden to allow for folded regions. * Overridden to allow for folded regions.
*/ */
@@ -610,18 +575,15 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
childAllocation2(lineCount - 1, curY, alloc); childAllocation2(lineCount - 1, curY, alloc);
return getView(lineCount - 1); return getView(lineCount - 1);
} }
/** /**
* Gives notification that something was inserted into the * Gives notification that something was inserted into the document in a
* document in a location that this view is responsible for. * location that this view is responsible for. This is implemented to simply
* This is implemented to simply update the children. * update the children.
* *
* @param changes * @param changes The change information from the associated document.
* The change information from the associated document. * @param a the current allocation of the view
* @param a * @param f the factory to use to rebuild if the view has children
* the current allocation of the view
* @param f
* the factory to use to rebuild if the view has children
* @see View#insertUpdate * @see View#insertUpdate
*/ */
@Override @Override
@@ -634,17 +596,14 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
v.insertUpdate(changes, alloc, f); v.insertUpdate(changes, alloc, f);
} }
} }
/** /**
* Loads all of the children to initialize the view. * Loads all of the children to initialize the view. This is called by the
* This is called by the <code>setParent</code> method. * <code>setParent</code> method. Subclasses can re-implement this to initialize
* Subclasses can re-implement this to initialize their * their child views in a different manner. The default implementation creates a
* child views in a different manner. The default * child view for each child element.
* implementation creates a child view for each
* child element.
* *
* @param f * @param f the view factory
* the view factory
*/ */
@Override @Override
protected void loadChildren(ViewFactory f) { protected void loadChildren(ViewFactory f) {
@@ -658,7 +617,7 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
replace(0, 0, added); replace(0, 0, added);
} }
} }
@Override @Override
public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
if (!isAllocationValid()) { if (!isAllocationValid()) {
@@ -691,48 +650,43 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
throw new BadLocationException("Position not represented by view", pos); throw new BadLocationException("Position not represented by view", pos);
} }
/** /**
* Provides a mapping, for a given region, from the document model * Provides a mapping, for a given region, from the document model coordinate
* coordinate space to the view coordinate space. The specified region is * space to the view coordinate space. The specified region is created as a
* created as a union of the first and last character positions. * union of the first and last character positions.
* <p> * <p>
* *
* This is implemented to subtract the width of the second character, as * This is implemented to subtract the width of the second character, as this
* this view's <code>modelToView</code> actually returns the width of the * view's <code>modelToView</code> actually returns the width of the character
* character instead of "1" or "0" like the View implementations in * instead of "1" or "0" like the View implementations in
* <code>javax.swing.text</code>. Thus, if we don't override this method, * <code>javax.swing.text</code>. Thus, if we don't override this method, the
* the <code>View</code> implementation will return one character's width * <code>View</code> implementation will return one character's width too much
* too much for its consumers (implementations of * for its consumers (implementations of
* <code>javax.swing.text.Highlighter</code>). * <code>javax.swing.text.Highlighter</code>).
* *
* @param p0 * @param p0 the position of the first character (&gt;=0)
* the position of the first character (&gt;=0) * @param b0 The bias of the first character position, toward the previous
* @param b0 * character or the next character represented by the offset, in case
* The bias of the first character position, toward the previous * the position is a boundary of two views; <code>b0</code> will have
* character or the next character represented by the offset, in * one of these values:
* case the position is a boundary of two views; <code>b0</code> * <ul>
* will have one of these values: * <li><code>Position.Bias.Forward</code>
* <ul> * <li><code>Position.Bias.Backward</code>
* <li><code>Position.Bias.Forward</code> * </ul>
* <li><code>Position.Bias.Backward</code> * @param p1 the position of the last character (&gt;=0)
* </ul> * @param b1 the bias for the second character position, defined one of the
* @param p1 * legal values shown above
* the position of the last character (&gt;=0) * @param a the area of the view, which encompasses the requested region
* @param b1 * @return the bounding box which is a union of the region specified by the
* the bias for the second character position, defined * first and last character positions
* one of the legal values shown above * @exception BadLocationException if the given position does not represent
* @param a * a valid location in the associated
* the area of the view, which encompasses the requested region * document
* @return the bounding box which is a union of the region specified * @exception IllegalArgumentException if <code>b0</code> or <code>b1</code> are
* by the first and last character positions * not one of the legal
* @exception BadLocationException * <code>Position.Bias</code> values listed
* if the given position does * above
* not represent a valid location in the associated document
* @exception IllegalArgumentException
* if <code>b0</code> or
* <code>b1</code> are not one of the
* legal <code>Position.Bias</code> values listed above
* @see View#viewToModel * @see View#viewToModel
*/ */
@Override @Override
@@ -774,17 +728,15 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
return r0; return r0;
} }
/** /**
* Returns the next tab stop position after a given reference position. * Returns the next tab stop position after a given reference position. This
* This implementation does not support things like centering so it * implementation does not support things like centering so it ignores the
* ignores the tabOffset argument. * tabOffset argument.
* *
* @param x * @param x the current position &gt;= 0
* the current position &gt;= 0 * @param tabOffset the position within the text stream that the tab occurred at
* @param tabOffset * &gt;= 0.
* the position within the text stream
* that the tab occurred at &gt;= 0.
* @return the tab stop, measured in points &gt;= 0 * @return the tab stop, measured in points &gt;= 0
*/ */
@Override @Override
@@ -795,14 +747,12 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
int ntabs = ((int) x - tabBase) / tabSize; int ntabs = ((int) x - tabBase) / tabSize;
return tabBase + ((ntabs + 1f) * tabSize); return tabBase + ((ntabs + 1f) * tabSize);
} }
/** /**
* Paints the word-wrapped text. * Paints the word-wrapped text.
* *
* @param g * @param g The graphics context in which to paint.
* The graphics context in which to paint. * @param a The shape (usually a rectangle) in which to paint.
* @param a
* The shape (usually a rectangle) in which to paint.
*/ */
@Override @Override
public void paint(Graphics g, Shape a) { public void paint(Graphics g, Shape a) {
@@ -854,18 +804,15 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
} }
} }
/** /**
* Gives notification that something was removed from the * Gives notification that something was removed from the document in a location
* document in a location that this view is responsible for. * that this view is responsible for. This is implemented to simply update the
* This is implemented to simply update the children. * children.
* *
* @param changes * @param changes The change information from the associated document.
* The change information from the associated document. * @param a the current allocation of the view
* @param a * @param f the factory to use to rebuild if the view has children
* the current allocation of the view
* @param f
* the factory to use to rebuild if the view has children
* @see View#removeUpdate * @see View#removeUpdate
*/ */
@Override @Override
@@ -878,20 +825,16 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
v.removeUpdate(changes, alloc, f); v.removeUpdate(changes, alloc, f);
} }
} }
/** /**
* Makes a <code>Segment</code> point to the text in our * Makes a <code>Segment</code> point to the text in our document between the
* document between the given positions. Note that the positions MUST be * given positions. Note that the positions MUST be valid positions in the
* valid positions in the document. * document.
* *
* @param p0 * @param p0 The first position in the document.
* The first position in the document. * @param p1 The second position in the document.
* @param p1 * @param document The document from which you want to get the text.
* The second position in the document. * @param seg The segment in which to load the text.
* @param document
* The document from which you want to get the text.
* @param seg
* The segment in which to load the text.
*/ */
private void setSegment(int p0, int p1, Document document, Segment seg) { private void setSegment(int p0, int p1, Document document, Segment seg) {
try { try {
@@ -904,15 +847,13 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
ble.printStackTrace(); ble.printStackTrace();
} }
} }
/** /**
* Sets the size of the view. This should cause layout of the view along * Sets the size of the view. This should cause layout of the view along the
* the given axis, if it has any layout duties. * given axis, if it has any layout duties.
* *
* @param width * @param width the width &gt;= 0
* the width &gt;= 0 * @param height the height &gt;= 0
* @param height
* the height &gt;= 0
*/ */
@Override @Override
public void setSize(float width, float height) { public void setSize(float width, float height) {
@@ -926,10 +867,9 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
super.setSize(width, height); super.setSize(width, height);
widthChanging = false; widthChanging = false;
} }
/** /**
* Update the child views in response to a * Update the child views in response to a document event.
* document event.
*/ */
void updateChildren(DocumentEvent e, Shape a) { void updateChildren(DocumentEvent e, Shape a) {
Element elem = getElement(); Element elem = getElement();
@@ -962,14 +902,14 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
// update font metrics which may be used by the child views // update font metrics which may be used by the child views
updateMetrics(); updateMetrics();
} }
final void updateMetrics() { final void updateMetrics() {
Component host = getContainer(); Component host = getContainer();
Font f = host.getFont(); Font f = host.getFont();
metrics = host.getFontMetrics(f); // Metrics for the default font. metrics = host.getFontMetrics(f); // Metrics for the default font.
tabSize = getTabSize() * metrics.charWidth('m'); tabSize = getTabSize() * metrics.charWidth('m');
} }
@Override @Override
public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) { public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) {
int offs = -1; int offs = -1;
@@ -992,7 +932,7 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
return offs; return offs;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -1001,7 +941,7 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
return yForLineContaining(alloc, getElement().getElement(line).getStartOffset()); return yForLineContaining(alloc, getElement().getElement(line).getStartOffset());
// return alloc.y + getOffset(Y_AXIS, line); // return alloc.y + getOffset(Y_AXIS, line);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -1024,25 +964,23 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
return -1; return -1;
} }
/** /**
* Simple view of a line that wraps if it doesn't * Simple view of a line that wraps if it doesn't fit within the horizontal
* fit within the horizontal space allocated. * space allocated. This class tries to be lightweight by carrying little state
* This class tries to be lightweight by carrying little * of it's own and sharing the state of the outer class with it's siblings.
* state of it's own and sharing the state of the outer class
* with it's siblings.
*/ */
class WrappedLine extends View { class WrappedLine extends View {
private int nlines; private int nlines;
WrappedLine(Element elem) { WrappedLine(Element elem) {
super(elem); super(elem);
} }
/** /**
* Calculate the number of lines that will be rendered * Calculate the number of lines that will be rendered by logical line when it
* by logical line when it is wrapped. * is wrapped.
*/ */
final int calculateLineCount() { final int calculateLineCount() {
int nlines = 0; int nlines = 0;
@@ -1062,7 +1000,8 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
for (int p0 = startOffset; p0 < p1;) { for (int p0 = startOffset; p0 < p1;) {
// System.err.println("... ... " + p0 + ", " + p1); // System.err.println("... ... " + p0 + ", " + p1);
nlines += 1; nlines += 1;
TokenSubList subList = TokenUtils.getSubTokenList(tokenList, p0, WrappedSyntaxView.this, textArea, x0, lineCountTempToken); TokenSubList subList = TokenUtils.getSubTokenList(tokenList, p0, WrappedSyntaxView.this, textArea, x0,
lineCountTempToken);
x0 = subList != null ? subList.x : x0; x0 = subList != null ? subList.x : x0;
tokenList = subList != null ? subList.tokenList : null; tokenList = subList != null ? subList.tokenList : null;
int p = calculateBreakPosition(p0, tokenList, x0); int p = calculateBreakPosition(p0, tokenList, x0);
@@ -1075,81 +1014,68 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
// System.err.println("... ... ... new p0==" + p0); // System.err.println("... ... ... new p0==" + p0);
} }
/* /*
* int numLines = 0; * int numLines = 0; try { numLines = textArea.getLineCount(); } catch
* try { * (BadLocationException ble) { ble.printStackTrace(); } System.err.
* numLines = textArea.getLineCount(); * println(">>> >>> calculated number of lines for this view (line " + line +
* } catch (BadLocationException ble) { * "/" + numLines + ": " + nlines);
* ble.printStackTrace();
* }
* System.err.
* println(">>> >>> calculated number of lines for this view (line "
* + line + "/" + numLines + ": " + nlines);
*/ */
return nlines; return nlines;
} }
/** /**
* Determines the preferred span for this view along an * Determines the preferred span for this view along an axis.
* axis.
* *
* @param axis * @param axis may be either X_AXIS or Y_AXIS
* may be either X_AXIS or Y_AXIS * @return the span the view would like to be rendered into. Typically the view
* @return the span the view would like to be rendered into. * is told to render into the span that is returned, although there is
* Typically the view is told to render into the span * no guarantee. The parent may choose to resize or break the view.
* that is returned, although there is no guarantee.
* The parent may choose to resize or break the view.
* @see View#getPreferredSpan * @see View#getPreferredSpan
*/ */
@Override @Override
public float getPreferredSpan(int axis) { public float getPreferredSpan(int axis) {
switch (axis) { switch (axis) {
case View.X_AXIS: case View.X_AXIS:
float width = getWidth(); float width = getWidth();
if (width == Integer.MAX_VALUE) { if (width == Integer.MAX_VALUE) {
// We have been initially set to MAX_VALUE, but we don't // We have been initially set to MAX_VALUE, but we don't
// want this as our preferred. // want this as our preferred.
return 100f; return 100f;
} }
return width; return width;
case View.Y_AXIS: case View.Y_AXIS:
if (nlines == 0 || widthChanging) { if (nlines == 0 || widthChanging) {
nlines = calculateLineCount(); nlines = calculateLineCount();
} }
int h = nlines * ((RSyntaxTextArea) getContainer()).getLineHeight(); int h = nlines * ((RSyntaxTextArea) getContainer()).getLineHeight();
return h; return h;
default: default:
throw new IllegalArgumentException("Invalid axis: " + axis); throw new IllegalArgumentException("Invalid axis: " + axis);
} }
} }
/** /**
* Renders using the given rendering surface and area on that * Renders using the given rendering surface and area on that surface. The view
* surface. The view may need to do layout and create child * may need to do layout and create child views to enable itself to render into
* views to enable itself to render into the given allocation. * the given allocation.
* *
* @param g * @param g the rendering surface to use
* the rendering surface to use * @param a the allocated region to render into
* @param a
* the allocated region to render into
* @see View#paint * @see View#paint
*/ */
@Override @Override
public void paint(Graphics g, Shape a) { public void paint(Graphics g, Shape a) {
// This is done by drawView() above. // This is done by drawView() above.
} }
/** /**
* Provides a mapping from the document model coordinate space * Provides a mapping from the document model coordinate space to the coordinate
* to the coordinate space of the view mapped to it. * space of the view mapped to it.
* *
* @param pos * @param pos the position to convert
* the position to convert * @param a the allocated region to render into
* @param a
* the allocated region to render into
* @return the bounding box of the given position is returned * @return the bounding box of the given position is returned
* @exception BadLocationException * @exception BadLocationException if the given position does not represent a
* if the given position does not * valid location in the associated document.
* represent a valid location in the associated document.
*/ */
@Override @Override
public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
@@ -1170,13 +1096,15 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
Token tokenList = doc.getTokenListForLine(line); Token tokenList = doc.getTokenListForLine(line);
float x0 = alloc.x;// 0; float x0 = alloc.x;// 0;
while (p0 < p1) { while (p0 < p1) {
TokenSubList subList = TokenUtils.getSubTokenList(tokenList, p0, WrappedSyntaxView.this, textArea, x0, lineCountTempToken); TokenSubList subList = TokenUtils.getSubTokenList(tokenList, p0, WrappedSyntaxView.this, textArea, x0,
lineCountTempToken);
x0 = subList != null ? subList.x : x0; x0 = subList != null ? subList.x : x0;
tokenList = subList != null ? subList.tokenList : null; tokenList = subList != null ? subList.tokenList : null;
int p = calculateBreakPosition(p0, tokenList, x0); int p = calculateBreakPosition(p0, tokenList, x0);
if ((pos >= p0) && (testP < p)) {// pos < p)) { if ((pos >= p0) && (testP < p)) {// pos < p)) {
// it's in this line // it's in this line
alloc = RSyntaxUtilities.getLineWidthUpTo(textArea, s, p0, pos, WrappedSyntaxView.this, alloc, alloc.x); alloc = RSyntaxUtilities.getLineWidthUpTo(textArea, s, p0, pos, WrappedSyntaxView.this, alloc,
alloc.x);
// System.err.println("--- end modelToView ---"); // System.err.println("--- end modelToView ---");
return alloc; return alloc;
} }
@@ -1184,7 +1112,8 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
if (p == p1 - 1 && pos == p1 - 1) { if (p == p1 - 1 && pos == p1 - 1) {
// Wants end. // Wants end.
if (pos > p0) { if (pos > p0) {
alloc = RSyntaxUtilities.getLineWidthUpTo(textArea, s, p0, pos, WrappedSyntaxView.this, alloc, alloc.x); alloc = RSyntaxUtilities.getLineWidthUpTo(textArea, s, p0, pos, WrappedSyntaxView.this, alloc,
alloc.x);
} }
// System.err.println("--- end modelToView ---"); // System.err.println("--- end modelToView ---");
return alloc; return alloc;
@@ -1195,19 +1124,16 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
} }
throw new BadLocationException(null, pos); throw new BadLocationException(null, pos);
} }
/** /**
* Provides a mapping from the view coordinate space to the logical * Provides a mapping from the view coordinate space to the logical coordinate
* coordinate space of the model. * space of the model.
* *
* @param fx * @param fx the X coordinate
* the X coordinate * @param fy the Y coordinate
* @param fy * @param a the allocated region to render into
* the Y coordinate * @return the location within the model that best represents the given point in
* @param a * the view
* the allocated region to render into
* @return the location within the model that best represents the
* given point in the view
* @see View#viewToModel * @see View#viewToModel
*/ */
@Override @Override
@@ -1247,8 +1173,8 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
// We can always use alloc.x since we always break // We can always use alloc.x since we always break
// lines so they start at the beginning of a physical // lines so they start at the beginning of a physical
// line. // line.
TokenSubList subList = TokenUtils.getSubTokenList(tlist, p0, WrappedSyntaxView.this, textArea, alloc.x, TokenSubList subList = TokenUtils.getSubTokenList(tlist, p0, WrappedSyntaxView.this, textArea,
lineCountTempToken); alloc.x, lineCountTempToken);
tlist = subList != null ? subList.tokenList : null; tlist = subList != null ? subList.tokenList : null;
int p = calculateBreakPosition(p0, tlist, alloc.x); int p = calculateBreakPosition(p0, tlist, alloc.x);
// If desired view position is in this physical chunk. // If desired view position is in this physical chunk.
@@ -1281,7 +1207,7 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
return getEndOffset() - 1; return getEndOffset() - 1;
} // End of else. } // End of else.
} }
private void handleDocumentEvent(DocumentEvent e, Shape a, ViewFactory f) { private void handleDocumentEvent(DocumentEvent e, Shape a, ViewFactory f) {
int n = calculateLineCount(); int n = calculateLineCount();
if (this.nlines != n) { if (this.nlines != n) {
@@ -1303,12 +1229,12 @@ public class WrappedSyntaxView extends BoxView implements TabExpander, RSTAView
c.repaint(alloc.x, alloc.y, alloc.width, alloc.height); c.repaint(alloc.x, alloc.y, alloc.width, alloc.height);
} }
} }
@Override @Override
public void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) { public void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) {
handleDocumentEvent(e, a, f); handleDocumentEvent(e, a, f);
} }
@Override @Override
public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) { public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) {
handleDocumentEvent(e, a, f); handleDocumentEvent(e, a, f);
@@ -9,8 +9,8 @@ import javax.swing.text.Element;
// import javax.swing.text.View; // import javax.swing.text.View;
/** /**
* Replacement for the old <code>WrappedSyntaxView</code> class, designed to * Replacement for the old <code>WrappedSyntaxView</code> class, designed to be
* be faster with large wrapped documents. Heavily based off of * faster with large wrapped documents. Heavily based off of
* <code>BoxView</code>, but streamlined to only care about the y-axis, and * <code>BoxView</code>, but streamlined to only care about the y-axis, and
* takes code folding into account. * takes code folding into account.
* <p> * <p>
@@ -25,7 +25,7 @@ public class WrappedSyntaxView2 {// extends CompositeView {
// private int[] cachedOffsets; // private int[] cachedOffsets;
// private int[] cachedSpans; // private int[] cachedSpans;
// private boolean sizeRequirementsValid; // private boolean sizeRequirementsValid;
public WrappedSyntaxView2(Element root) { public WrappedSyntaxView2(Element root) {
// super(root); // super(root);
// tempRect = new Rectangle(); // tempRect = new Rectangle();
@@ -21,10 +21,10 @@ import org.fife.ui.rtextarea.SmartHighlightPainter;
* @version 1.0 * @version 1.0
*/ */
public class XmlOccurrenceMarker implements OccurrenceMarker { public class XmlOccurrenceMarker implements OccurrenceMarker {
private static final char[] CLOSE_TAG_START = { '<', '/' }; private static final char[] CLOSE_TAG_START = { '<', '/' };
private static final char[] TAG_SELF_CLOSE = { '/', '>' }; private static final char[] TAG_SELF_CLOSE = { '/', '>' };
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -32,7 +32,7 @@ public class XmlOccurrenceMarker implements OccurrenceMarker {
public Token getTokenToMark(RSyntaxTextArea textArea) { public Token getTokenToMark(RSyntaxTextArea textArea) {
return HtmlOccurrenceMarker.getTagNameTokenForCaretOffset(textArea, this); return HtmlOccurrenceMarker.getTagNameTokenForCaretOffset(textArea, this);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -40,7 +40,7 @@ public class XmlOccurrenceMarker implements OccurrenceMarker {
public boolean isValidType(RSyntaxTextArea textArea, Token t) { public boolean isValidType(RSyntaxTextArea textArea, Token t) {
return textArea.getMarkOccurrencesOfTokenType(t.getType()); return textArea.getMarkOccurrencesOfTokenType(t.getType());
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -173,15 +173,15 @@ public class XmlOccurrenceMarker implements OccurrenceMarker {
} while (curLine >= 0); } while (curLine >= 0);
} }
} }
/** /**
* Used internally when searching backward for a matching "open" tag. * Used internally when searching backward for a matching "open" tag.
*/ */
private static class Entry { private static class Entry {
private boolean open; private boolean open;
private Token t; private Token t;
Entry(boolean open, Token t) { Entry(boolean open, Token t) {
this.open = open; this.open = open;
this.t = t; this.t = t;
Loaded 100 of 211 files, more files were not shown because too many files have changed in this diff. Show more