There are two classes here. One renders XML transcripts in JTextPane, and the other uses XPath to navigate the transcripts. Neither is part of the build yet. I'll document them more fully later when I've got to a point where they are worth sharing.
This commit is contained in:
parent
86c2374706
commit
3199ff7926
2 changed files with 198 additions and 64 deletions
|
@ -1,76 +1,30 @@
|
|||
package org.thdl.quilldriver;
|
||||
|
||||
import org.jaxen.jdom.JDOMXPath;
|
||||
import org.jaxen.XPath;
|
||||
import org.jaxen.JaxenException;
|
||||
import org.jaxen.jdom.JDOMXPath;
|
||||
import java.util.List;
|
||||
|
||||
public class TranscriptNavigator {
|
||||
private boolean autoInsertFlag = false;
|
||||
private TranscriptMediator mediator;
|
||||
private TranscriptNavigator() {} //can't instantiate this class
|
||||
|
||||
TranscriptNavigator(TranscriptMediator mediator) {
|
||||
this.mediator = mediator;
|
||||
public static Object findSingleNode(Object jdomNode, String xpathExpression) {
|
||||
List l = findNodeSet(jdomNode, xpathExpression);
|
||||
if (l == null || l.size() == 0)
|
||||
return null;
|
||||
else {
|
||||
return l.get(0);
|
||||
}
|
||||
|
||||
/*
|
||||
Next = ancestor-or-self::S/following-sibling::
|
||||
*/
|
||||
|
||||
public boolean edit(String xpathExpression) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean editNextText(String elementName) {
|
||||
int pos = mediator.getPane().getCaretPosition();
|
||||
|
||||
Object next = next(pos, elementName);
|
||||
if (next == null) {
|
||||
if (autoInsertFlag) {
|
||||
//insert after
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean editPrevText(String elementName) {
|
||||
pos = mediator.getPane().getCaretPosition();
|
||||
|
||||
Object prev = prev(pos, elementName);
|
||||
if (prev == null) {
|
||||
if (autoInsertFlag) {
|
||||
//insert after
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean highlightNext(String elementName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean highlightPrev(String elementName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object next(int pos, String elementName) {
|
||||
Object jdomNode = mediator.getNodeAtPos(int position);
|
||||
public static List findNodeSet(Object jdomNode, String xpathExpression) {
|
||||
if (jdomNode == null)
|
||||
return null;
|
||||
XPath path = new JDOMXPath("a/b/c");
|
||||
List results = path.selectNodes(jdomNode);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object prev(int pos, String elementName) {
|
||||
Object jdomNode = mediator.getNodeAtPos(int position);
|
||||
if (jdomNode == null)
|
||||
return null;
|
||||
XPath path = new JDOMXPath("a/b/c");
|
||||
List results = path.selectNodes(jdomNode);
|
||||
try {
|
||||
XPath path = new JDOMXPath(xpathExpression);
|
||||
return path.selectNodes(jdomNode);
|
||||
} catch (JaxenException je) {
|
||||
je.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
180
source/org/thdl/quilldriver/TranscriptRenderer.java
Normal file
180
source/org/thdl/quilldriver/TranscriptRenderer.java
Normal file
|
@ -0,0 +1,180 @@
|
|||
package org.thdl.quilldriver;
|
||||
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.Attribute;
|
||||
import org.jdom.Text;
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.text.Position;
|
||||
import javax.swing.text.StyleConstants;
|
||||
import javax.swing.text.StyledDocument;
|
||||
import javax.swing.text.AttributeSet;
|
||||
import javax.swing.text.SimpleAttributeSet;
|
||||
import javax.swing.text.BadLocationException;
|
||||
|
||||
public class TranscriptRenderer {
|
||||
private Document xml;
|
||||
private JTextPane pane;
|
||||
private StyledDocument doc;
|
||||
private Map startOffsets, endOffsets;
|
||||
private final float indentIncrement = 15.0F;
|
||||
private final Color tagColor = Color.magenta;
|
||||
private final Color attColor = Color.pink;
|
||||
private final Color textColor = Color.gray;
|
||||
|
||||
public TranscriptRenderer(Document xmlDoc, JTextPane textPane) {
|
||||
xml = xmlDoc;
|
||||
pane = textPane;
|
||||
render();
|
||||
}
|
||||
|
||||
public void render() {
|
||||
doc = pane.getStyledDocument();
|
||||
int len = doc.getLength();
|
||||
if (len > 0) {
|
||||
try {
|
||||
doc.remove(0, len);
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
startOffsets = new HashMap();
|
||||
endOffsets = new HashMap();
|
||||
Element root = xml.getRootElement();
|
||||
renderElement(root, 0.0F);
|
||||
|
||||
//replace Integer values in startOffsets and endOffsets with Positions
|
||||
Set startKeys = startOffsets.keySet();
|
||||
Iterator iter = startKeys.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Object key = iter.next();
|
||||
Integer val = (Integer)startOffsets.get(key);
|
||||
try {
|
||||
startOffsets.put(key, doc.createPosition(val.intValue()));
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
Set endKeys = endOffsets.keySet();
|
||||
iter = endKeys.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Object key = iter.next();
|
||||
Integer val = (Integer)endOffsets.get(key);
|
||||
try {
|
||||
endOffsets.put(key, doc.createPosition(val.intValue()));
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderElement(Element e, float indent) {
|
||||
SimpleAttributeSet eAttributes = new SimpleAttributeSet();
|
||||
StyleConstants.setLeftIndent(eAttributes, indent);
|
||||
SimpleAttributeSet eColor = new SimpleAttributeSet();
|
||||
StyleConstants.setForeground(eColor, tagColor);
|
||||
eColor.addAttribute("xmlnode", e);
|
||||
try {
|
||||
int start = doc.getLength();
|
||||
startOffsets.put(e, new Integer(start));
|
||||
doc.insertString(doc.getLength(), e.getQualifiedName(), eColor); //insert element begin tag
|
||||
List attributes = e.getAttributes();
|
||||
Iterator iter = attributes.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Attribute att = (Attribute)iter.next();
|
||||
renderAttribute(att);
|
||||
}
|
||||
doc.insertString(doc.getLength(), " {", eColor);
|
||||
doc.setParagraphAttributes(start, doc.getLength(), eAttributes, false);
|
||||
doc.insertString(doc.getLength(), "\n", null);
|
||||
List list = e.getContent();
|
||||
iter = list.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Object next = iter.next();
|
||||
if (next instanceof Element)
|
||||
renderElement((Element)next, indent + indentIncrement);
|
||||
else if (next instanceof Text) {
|
||||
Text t = (Text)next;
|
||||
if (t.getTextTrim().length() > 0)
|
||||
renderText(t, indent + indentIncrement);
|
||||
}
|
||||
// Also: Comment ProcessingInstruction CDATA EntityRef
|
||||
}
|
||||
start = doc.getLength();
|
||||
doc.insertString(start, "}", eColor); //insert element end tag
|
||||
doc.setParagraphAttributes(start, doc.getLength(), eAttributes, false);
|
||||
endOffsets.put(e, new Integer(doc.getLength()));
|
||||
doc.insertString(doc.getLength(), "\n", null);
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void renderAttribute(Attribute att) {
|
||||
SimpleAttributeSet aColor = new SimpleAttributeSet();
|
||||
StyleConstants.setForeground(aColor, attColor);
|
||||
SimpleAttributeSet tColor = new SimpleAttributeSet();
|
||||
StyleConstants.setForeground(tColor, textColor);
|
||||
tColor.addAttribute("xmlnode", att);
|
||||
String name = att.getQualifiedName();
|
||||
String value = att.getValue();
|
||||
try {
|
||||
doc.insertString(doc.getLength(), " "+att.getQualifiedName()+"=", aColor);
|
||||
startOffsets.put(att, new Integer(doc.getLength()));
|
||||
doc.insertString(doc.getLength(), "\"" +att.getValue()+"\"", tColor);
|
||||
endOffsets.put(att, new Integer(doc.getLength()));
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void renderText(Text t, float indent) {
|
||||
SimpleAttributeSet tAttributes = new SimpleAttributeSet();
|
||||
StyleConstants.setLeftIndent(tAttributes, indent);
|
||||
StyleConstants.setForeground(tAttributes, textColor);
|
||||
tAttributes.addAttribute("xmlnode", t);
|
||||
try {
|
||||
String s = t.getTextTrim();
|
||||
int start = doc.getLength()-1;
|
||||
startOffsets.put(t, new Integer(start));
|
||||
doc.insertString(doc.getLength(), s, null); //insert text
|
||||
int end = doc.getLength();
|
||||
endOffsets.put(t, new Integer(end));
|
||||
doc.setParagraphAttributes(start+1, end-start, tAttributes, false);
|
||||
doc.insertString(doc.getLength(), "\n", null);
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Object getNodeForOffset(int offset) {
|
||||
AttributeSet attSet = doc.getCharacterElement(offset).getAttributes();
|
||||
return attSet.getAttribute("xmlnode");
|
||||
}
|
||||
|
||||
public int getStartOffsetForNode(Object node) {
|
||||
Position pos = (Position)startOffsets.get(node);
|
||||
if (pos == null) return -1;
|
||||
else return pos.getOffset();
|
||||
}
|
||||
|
||||
public int getEndOffsetForNode(Object node) {
|
||||
Position pos = (Position)endOffsets.get(node);
|
||||
if (pos == null) return -1;
|
||||
else return pos.getOffset();
|
||||
}
|
||||
|
||||
public boolean isEditable(Object node) {
|
||||
if (node == null) return false;
|
||||
else if (node instanceof Element) return false;
|
||||
else if (node instanceof Text) return true;
|
||||
else if (node instanceof Attribute) return true;
|
||||
else return false;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue