From 3199ff79268b94dc876718a00e21c37dec954ca5 Mon Sep 17 00:00:00 2001 From: eg3p Date: Thu, 12 Dec 2002 15:17:42 +0000 Subject: [PATCH] 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. --- .../thdl/quilldriver/TranscriptNavigator.java | 82 ++------ .../thdl/quilldriver/TranscriptRenderer.java | 180 ++++++++++++++++++ 2 files changed, 198 insertions(+), 64 deletions(-) create mode 100644 source/org/thdl/quilldriver/TranscriptRenderer.java diff --git a/source/org/thdl/quilldriver/TranscriptNavigator.java b/source/org/thdl/quilldriver/TranscriptNavigator.java index 7a4fde9..6cfb216 100644 --- a/source/org/thdl/quilldriver/TranscriptNavigator.java +++ b/source/org/thdl/quilldriver/TranscriptNavigator.java @@ -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; +public class TranscriptNavigator { + private TranscriptNavigator() {} //can't instantiate this class - TranscriptNavigator(TranscriptMediator mediator) { - this.mediator = mediator; - } - - /* - 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; + 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); } - 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) + try { + XPath path = new JDOMXPath(xpathExpression); + return path.selectNodes(jdomNode); + } catch (JaxenException je) { + je.printStackTrace(); return null; - XPath path = new JDOMXPath("a/b/c"); - List results = path.selectNodes(jdomNode); - return null; + } } } diff --git a/source/org/thdl/quilldriver/TranscriptRenderer.java b/source/org/thdl/quilldriver/TranscriptRenderer.java new file mode 100644 index 0000000..f1a123e --- /dev/null +++ b/source/org/thdl/quilldriver/TranscriptRenderer.java @@ -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; + } +}