1023 lines
36 KiB
Java
1023 lines
36 KiB
Java
/*
|
|
The contents of this file are subject to the THDL Open Community License
|
|
Version 1.0 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License on the THDL web site
|
|
(http://www.thdl.org/).
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
License for the specific terms governing rights and limitations under the
|
|
License.
|
|
|
|
The Initial Developer of this software is the Tibetan and Himalayan Digital
|
|
Library (THDL). Portions created by the THDL are Copyright 2001 THDL.
|
|
All Rights Reserved.
|
|
|
|
Contributor(s): ______________________________________.
|
|
*/
|
|
|
|
package org.thdl.quilldriver;
|
|
|
|
import java.util.*;
|
|
import java.io.*;
|
|
import java.net.*;
|
|
import javax.swing.*;
|
|
import javax.swing.table.*;
|
|
import javax.swing.event.*;
|
|
import javax.swing.text.*;
|
|
import javax.swing.plaf.*;
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import java.lang.reflect.*;
|
|
|
|
import org.thdl.media.SmartMoviePanel;
|
|
import org.thdl.media.SmartMoviePanelException;
|
|
import org.thdl.savant.JdkVersionHacks;
|
|
import org.thdl.savant.TextHighlightPlayer;
|
|
import org.thdl.quilldriver.XMLView;
|
|
import org.thdl.quilldriver.XMLEditor;
|
|
import org.thdl.quilldriver.XMLUtilities;
|
|
import org.thdl.util.ThdlDebug;
|
|
import org.thdl.util.ThdlActionListener;
|
|
import org.thdl.util.ThdlAbstractAction;
|
|
import org.thdl.util.ThdlOptions;
|
|
import org.thdl.util.SimpleSpinner;
|
|
import org.thdl.util.ThdlI18n;
|
|
|
|
import org.jdom.DocType;
|
|
import org.jdom.Document;
|
|
import org.jdom.Element;
|
|
import org.jdom.Text;
|
|
import org.jdom.JDOMException;
|
|
import org.jdom.input.SAXBuilder;
|
|
import org.jdom.input.DOMBuilder;
|
|
import org.jdom.output.XMLOutputter;
|
|
import org.jdom.output.DOMOutputter;
|
|
import org.jdom.transform.JDOMSource;
|
|
import org.jdom.transform.JDOMResult;
|
|
|
|
import javax.xml.transform.Transformer;
|
|
import javax.xml.transform.TransformerFactory;
|
|
import javax.xml.transform.TransformerException;
|
|
import javax.xml.transform.TransformerConfigurationException;
|
|
import javax.xml.transform.dom.DOMSource;
|
|
import javax.xml.transform.dom.DOMResult;
|
|
import javax.xml.transform.stream.StreamSource;
|
|
import javax.xml.transform.stream.StreamResult;
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
|
|
import javax.swing.JTextPane;
|
|
import javax.swing.JTextField;
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JButton;
|
|
import javax.swing.text.AttributeSet;
|
|
import javax.swing.text.StyledDocument;
|
|
import javax.swing.text.StyleConstants;
|
|
import java.util.List;
|
|
import java.util.Enumeration;
|
|
import java.util.StringTokenizer;
|
|
import java.awt.Color;
|
|
import java.awt.BorderLayout;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.WindowEvent;
|
|
import java.awt.event.WindowAdapter;
|
|
|
|
import java.io.File;
|
|
import java.net.URL;
|
|
import java.net.MalformedURLException;
|
|
|
|
public class QD extends JDesktopPane {
|
|
protected SmartMoviePanel player = null;
|
|
protected XMLEditor editor = null;
|
|
protected JInternalFrame videoFrame = null;
|
|
protected JInternalFrame textFrame = null;
|
|
protected JInternalFrame actionFrame = null;
|
|
protected ResourceBundle messages;
|
|
protected TimeCodeManager tcp = null;
|
|
protected Hashtable actions;
|
|
protected Properties config; //xpath based properties
|
|
protected Properties textConfig; //unchangeable properties
|
|
protected JMenu[] configMenus;
|
|
protected XMLView view;
|
|
protected TextHighlightPlayer hp;
|
|
protected DocumentBuilder docBuilder;
|
|
protected File transcriptFile = null;
|
|
protected XMLTagInfo tagInfo = null;
|
|
protected String configURL, newURL, editURL, dtdURL, rootElement;
|
|
|
|
public QD(String configURL, String editURL, String newURL, String dtdURL) {
|
|
messages = ThdlI18n.getResourceBundle();
|
|
|
|
this.configURL = configURL;
|
|
this.newURL = newURL;
|
|
this.editURL = editURL;
|
|
this.dtdURL = dtdURL;
|
|
|
|
configure(configURL);
|
|
|
|
setBackground(new JFrame().getBackground());
|
|
setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
|
|
|
|
//(String title, boolean resizable, boolean closable, boolean maximizable, boolean iconifiable)
|
|
videoFrame = new JInternalFrame(null, false, false, false, false);
|
|
videoFrame.setVisible(true);
|
|
videoFrame.setLocation(0,0);
|
|
videoFrame.setSize(0,0);
|
|
add(videoFrame, JLayeredPane.POPUP_LAYER);
|
|
invalidate();
|
|
validate();
|
|
repaint();
|
|
|
|
textFrame = new JInternalFrame(null, false, false, false, true);
|
|
textFrame.setVisible(true);
|
|
textFrame.setLocation(0,0);
|
|
textFrame.setSize(0,0);
|
|
add(textFrame, JLayeredPane.DEFAULT_LAYER);
|
|
invalidate();
|
|
validate();
|
|
repaint();
|
|
|
|
actionFrame = new JInternalFrame(null, false, false, false, true);
|
|
actionFrame.setVisible(true);
|
|
actionFrame.setLocation(0,0);
|
|
actionFrame.setSize(0,0);
|
|
add(actionFrame, JLayeredPane.DEFAULT_LAYER);
|
|
invalidate();
|
|
validate();
|
|
repaint();
|
|
|
|
addComponentListener(new ComponentAdapter() {
|
|
public void componentResized(ComponentEvent ce) {
|
|
Dimension d = videoFrame.getSize();
|
|
if (d.width == 0 && d.height == 0)
|
|
videoFrame.setSize(getSize().width / 2, 0);
|
|
textFrame.setLocation(videoFrame.getSize().width, 0);
|
|
textFrame.setSize(getSize().width - videoFrame.getSize().width, getSize().height);
|
|
actionFrame.setLocation(0, videoFrame.getSize().height);
|
|
actionFrame.setSize(videoFrame.getSize().width, getSize().height - videoFrame.getSize().height);
|
|
}
|
|
});
|
|
|
|
try {
|
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
|
docBuilder = dbf.newDocumentBuilder();
|
|
} catch (ParserConfigurationException pce) {
|
|
pce.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private void startTimer() {
|
|
final java.util.Timer timer = new java.util.Timer(true);
|
|
timer.schedule(new TimerTask() {
|
|
public void run()
|
|
{
|
|
if (player.isInitialized())
|
|
{
|
|
timer.cancel();
|
|
tcp = new TimeCodeManager();
|
|
actionFrame.setContentPane(tcp);
|
|
actionFrame.pack();
|
|
invalidate();
|
|
validate();
|
|
repaint();
|
|
videoFrame.setContentPane(player);
|
|
videoFrame.pack();
|
|
videoFrame.setMaximumSize(videoFrame.getSize());
|
|
invalidate();
|
|
validate();
|
|
repaint();
|
|
textFrame.setLocation(videoFrame.getSize().width, 0);
|
|
textFrame.setSize(getSize().width - videoFrame.getSize().width, getSize().height);
|
|
invalidate();
|
|
validate();
|
|
repaint();
|
|
actionFrame.setLocation(0, videoFrame.getSize().height);
|
|
actionFrame.setSize(videoFrame.getSize().width, getSize().height - videoFrame.getSize().height);
|
|
invalidate();
|
|
validate();
|
|
repaint();
|
|
}
|
|
}}, 0, 50);
|
|
}
|
|
|
|
private void createActionTable(JTextComponent textComponent) {
|
|
actions = new Hashtable();
|
|
Action[] actionsArray = textComponent.getActions();
|
|
for (int i = 0; i < actionsArray.length; i++) {
|
|
Action a = actionsArray[i];
|
|
actions.put(a.getValue(Action.NAME), a);
|
|
}
|
|
}
|
|
|
|
private Action getActionByName(String name) {
|
|
return (Action)(actions.get(name));
|
|
}
|
|
|
|
class TimeCodeManager extends JPanel {
|
|
SimpleSpinner inSpinner, outSpinner;
|
|
|
|
TimeCodeManager() {
|
|
setLayout(new BorderLayout());
|
|
JPanel inPanel = new JPanel();
|
|
JButton inButton = new JButton(messages.getString("In"));
|
|
inSpinner = new SimpleSpinner();
|
|
inSpinner.setValue(new Integer(0));
|
|
inSpinner.setPreferredSize(new Dimension(100, inButton.getPreferredSize().height));
|
|
inPanel.add(inButton);
|
|
inPanel.add(inSpinner);
|
|
|
|
inButton.addActionListener(new ThdlActionListener() {
|
|
public void theRealActionPerformed(ActionEvent e) {
|
|
int k = player.getCurrentTime();
|
|
if (k != -1)
|
|
setInTime(k);
|
|
}
|
|
});
|
|
|
|
|
|
JPanel outPanel = new JPanel();
|
|
JButton outButton = new JButton(messages.getString("Out"));
|
|
outSpinner = new SimpleSpinner();
|
|
outSpinner.setValue(new Integer(player.getEndTime()));
|
|
outSpinner.setPreferredSize(new Dimension(100, inButton.getPreferredSize().height));
|
|
outPanel.add(outButton);
|
|
outPanel.add(outSpinner);
|
|
|
|
outButton.addActionListener(new ThdlActionListener() {
|
|
public void theRealActionPerformed(ActionEvent e) {
|
|
int k = player.getCurrentTime();
|
|
if (k != -1) {
|
|
setOutTime(k);
|
|
try {
|
|
player.cmd_stop();
|
|
} catch (SmartMoviePanelException smpe) {
|
|
smpe.printStackTrace();
|
|
ThdlDebug.noteIffyCode();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
JButton playSegButton = new JButton(messages.getString("PlaySegment"));
|
|
playSegButton.addActionListener(new ThdlActionListener() {
|
|
public void theRealActionPerformed(ActionEvent e) {
|
|
Integer in = getInTime();
|
|
Integer out = getOutTime();
|
|
if (out.intValue() > in.intValue()) {
|
|
try {
|
|
player.cmd_playSegment(in, out);
|
|
} catch (SmartMoviePanelException smpe) {
|
|
smpe.printStackTrace();
|
|
ThdlDebug.noteIffyCode();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
JPanel ps = new JPanel();
|
|
ps.add(playSegButton);
|
|
|
|
JButton playPauseButton = new JButton(messages.getString("PlayPause"));
|
|
playPauseButton.addActionListener(new ThdlActionListener() {
|
|
public void theRealActionPerformed(ActionEvent e) {
|
|
if (player != null && player.getMediaURL() != null) {
|
|
try {
|
|
if (player.isPlaying())
|
|
player.cmd_stop();
|
|
else
|
|
player.cmd_playOn();
|
|
} catch (SmartMoviePanelException smpe) {
|
|
smpe.printStackTrace();
|
|
ThdlDebug.noteIffyCode();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
JPanel playPausePanel = new JPanel();
|
|
playPausePanel.add(playPauseButton);
|
|
|
|
Box box = Box.createVerticalBox();
|
|
box.add(inPanel);
|
|
box.add(outPanel);
|
|
box.add(ps);
|
|
box.add(playPausePanel);
|
|
|
|
add("North", box);
|
|
}
|
|
public Integer getInTime() {
|
|
return inSpinner.getValue();
|
|
}
|
|
public Integer getOutTime() {
|
|
return outSpinner.getValue();
|
|
}
|
|
public void setInTime(int k) {
|
|
inSpinner.setValue(new Integer(k));
|
|
}
|
|
public void setOutTime(int k) {
|
|
outSpinner.setValue(new Integer(k));
|
|
}
|
|
public void setTimes(Object node) {
|
|
Object playableparent = XMLUtilities.findSingleNode(node, config.getProperty("qd.nearestplayableparent"));
|
|
if (playableparent == null) return;
|
|
String t1 = XMLUtilities.getTextForNode(XMLUtilities.findSingleNode(playableparent, config.getProperty("qd.nodebegins")));
|
|
String t2 = XMLUtilities.getTextForNode(XMLUtilities.findSingleNode(playableparent, config.getProperty("qd.nodeends")));
|
|
float f1 = new Float(t1).floatValue()*1000;
|
|
float f2 = new Float(t2).floatValue()*1000;
|
|
setInTime(new Float(f1).intValue());
|
|
setOutTime(new Float(f2).intValue());
|
|
}
|
|
}
|
|
|
|
public void setMediaPlayer(SmartMoviePanel smp) {
|
|
if (smp == null)
|
|
player = null;
|
|
else if (player == null || !player.equals(smp)) {
|
|
player = smp;
|
|
player.setParentContainer(QD.this);
|
|
}
|
|
}
|
|
public SmartMoviePanel getMediaPlayer() {
|
|
return player;
|
|
}
|
|
|
|
public boolean saveTranscript() {
|
|
if (transcriptFile == null)
|
|
return true;
|
|
|
|
XMLOutputter xmlOut = new XMLOutputter();
|
|
try {
|
|
FileOutputStream fous = new FileOutputStream(transcriptFile);
|
|
xmlOut.output(editor.getXMLDocument(), fous);
|
|
return true;
|
|
} catch (FileNotFoundException fnfe) {
|
|
fnfe.printStackTrace();
|
|
ThdlDebug.noteIffyCode();
|
|
return false;
|
|
} catch (IOException ioe) {
|
|
ioe.printStackTrace();
|
|
ThdlDebug.noteIffyCode();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public boolean newTranscript(File file, String mediaURL) {
|
|
try {
|
|
if (newURL == null) return false;
|
|
StreamSource gg = new StreamSource(newURL);
|
|
System.out.println(gg.getSystemId());
|
|
final Transformer transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(newURL));
|
|
transformer.setParameter("qd.mediaURL", mediaURL);
|
|
transformer.transform(new StreamSource(newURL), new StreamResult(file)); //no args constructor implies default tree with empty root
|
|
transformer.clearParameters();
|
|
if (loadTranscript(file)) {
|
|
if (dtdURL != null && rootElement != null) editor.getXMLDocument().setDocType(new DocType(rootElement,dtdURL));
|
|
return true;
|
|
}
|
|
} catch (TransformerException tre) {
|
|
tre.printStackTrace();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean loadTranscript(File file) {
|
|
if (!file.exists())
|
|
return false;
|
|
|
|
if (player == null) {
|
|
JOptionPane.showConfirmDialog(QD.this, messages.getString("SupportedMediaError"), null, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
final SAXBuilder builder = new SAXBuilder();
|
|
final JTextPane t = new JTextPane();
|
|
editor = new XMLEditor(builder.build(file), t, tagInfo);
|
|
/*final JTextField xpathField = new JTextField();
|
|
JButton goXPath = new JButton("Find XPATH");
|
|
goXPath.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
}
|
|
});
|
|
|
|
final JTextField taskField = new JTextField();
|
|
JButton goTask = new JButton("Execute Task");
|
|
*/
|
|
|
|
view = new XMLView(editor, editor.getXMLDocument(), config.getProperty("qd.timealignednodes"), config.getProperty("qd.nodebegins"), config.getProperty("qd.nodeends"));
|
|
hp = new TextHighlightPlayer(view, Color.cyan);
|
|
/*
|
|
JPanel top = new JPanel(new BorderLayout());
|
|
JPanel top1 = new JPanel(new BorderLayout());
|
|
top1.add("Center", xpathField);
|
|
top1.add("East", goXPath);
|
|
JPanel top2 = new JPanel(new BorderLayout());
|
|
top2.add("Center", taskField);
|
|
top2.add("East", goTask);
|
|
top.add("North", top1);
|
|
top.add("South", top2);
|
|
*/
|
|
JPanel p = new JPanel(new BorderLayout());
|
|
//p.add("North", top);
|
|
p.add("Center", hp);
|
|
|
|
if (player.getMediaURL() != null) {
|
|
try {
|
|
player.cmd_stop();
|
|
player.destroy();
|
|
} catch (SmartMoviePanelException smpe) {
|
|
smpe.printStackTrace();
|
|
ThdlDebug.noteIffyCode();
|
|
return false;
|
|
}
|
|
videoFrame.getContentPane().remove(player);
|
|
videoFrame.getContentPane().invalidate();
|
|
videoFrame.getContentPane().validate();
|
|
videoFrame.getContentPane().repaint();
|
|
videoFrame.setSize(new Dimension(QD.this.getSize().width / 2, 0));
|
|
actionFrame.setLocation(0,0);
|
|
actionFrame.setSize(new Dimension(actionFrame.getSize().width, QD.this.getSize().height));
|
|
}
|
|
|
|
Object mediaURL = XMLUtilities.findSingleNode(editor.getXMLDocument(), config.getProperty("qd.mediaurl"));
|
|
String value = XMLUtilities.getTextForNode(mediaURL);
|
|
if (value == null)
|
|
return false;
|
|
player.loadMovie(new URL(value));
|
|
player.addAnnotationPlayer(hp);
|
|
player.initForSavant(convertTimesForSmartMoviePanel(view.getT1s()), convertTimesForSmartMoviePanel(view.getT2s()), view.getIDs());
|
|
videoFrame.addMouseListener(new MouseAdapter() {
|
|
public void mouseClicked(MouseEvent e) {
|
|
System.out.println("mouse clicked on player");
|
|
//SmartMoviePanel smp = (SmartMoviePanel)e.getSource();
|
|
videoFrame.requestFocus();
|
|
}
|
|
});
|
|
startTimer();
|
|
|
|
textFrame.setContentPane(p);
|
|
textFrame.setSize(textFrame.getSize().width, getSize().height);
|
|
textFrame.invalidate();
|
|
textFrame.validate();
|
|
textFrame.repaint();
|
|
|
|
editor.addNodeEditListener(new XMLEditor.NodeEditListener() {
|
|
public void nodeEditPerformed(XMLEditor.NodeEditEvent ned) {
|
|
if (ned instanceof XMLEditor.StartEditEvent) {
|
|
//stop the automatic highlighting and scrolling
|
|
//since it would interfere with editing
|
|
player.cancelAnnotationTimer();
|
|
player.setAutoScrolling(false);
|
|
if (tcp != null) tcp.setTimes(ned.getNode());
|
|
} else if (ned instanceof XMLEditor.EndEditEvent) {
|
|
//turn auto-scrolling and highlighting back on
|
|
XMLEditor.EndEditEvent eee = (XMLEditor.EndEditEvent)ned;
|
|
if (eee.hasBeenEdited()) {
|
|
view.refresh();
|
|
hp.refresh();
|
|
}
|
|
player.setAutoScrolling(true);
|
|
} else if (ned instanceof XMLEditor.CantEditEvent) {
|
|
//if this node can't be edited, maybe it can be played!
|
|
System.out.println(ned.getNode().toString());
|
|
Object node = ned.getNode();
|
|
if (node != null) {
|
|
editor.getTextPane().setCaretPosition(editor.getStartOffsetForNode(node));
|
|
playNode(node);
|
|
if (tcp != null) tcp.setTimes(node);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
editor.setEditabilityTracker(true);
|
|
|
|
transcriptFile = file;
|
|
return true;
|
|
} catch (JDOMException jdome) {
|
|
jdome.printStackTrace();
|
|
transcriptFile = null;
|
|
return false;
|
|
} catch (MalformedURLException murle) {
|
|
murle.printStackTrace();
|
|
transcriptFile = null;
|
|
return false;
|
|
} catch (SmartMoviePanelException smpe) {
|
|
smpe.printStackTrace();
|
|
transcriptFile = null;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void playNode(Object node) {
|
|
Object playableparent = XMLUtilities.findSingleNode(node, config.getProperty("qd.nearestplayableparent"));
|
|
if (playableparent == null) return;
|
|
String nodeid = String.valueOf(playableparent.hashCode());
|
|
if (player.cmd_isID(nodeid)) {
|
|
editor.getTextPane().transferFocus();
|
|
player.cmd_playS(nodeid);
|
|
}
|
|
}
|
|
public void setEditable(boolean bool) {
|
|
}
|
|
|
|
/* FIXME: needs better error handling */
|
|
/** Creates an object via reflection.
|
|
* @return nonnull on success, null on error */
|
|
public static Object createObject(Constructor constructor, Object[] arguments) {
|
|
System.out.println ("Constructor: " + constructor.toString());
|
|
Object object = null;
|
|
try {
|
|
object = constructor.newInstance(arguments);
|
|
System.out.println ("Object: " + object.toString());
|
|
return object;
|
|
} catch (InstantiationException e) {
|
|
System.out.println(e);
|
|
ThdlDebug.noteIffyCode();
|
|
} catch (IllegalAccessException e) {
|
|
System.out.println(e);
|
|
ThdlDebug.noteIffyCode();
|
|
} catch (IllegalArgumentException e) {
|
|
System.out.println(e);
|
|
ThdlDebug.noteIffyCode();
|
|
} catch (InvocationTargetException e) {
|
|
System.out.println(e);
|
|
System.out.println(e.getTargetException());
|
|
ThdlDebug.noteIffyCode();
|
|
}
|
|
return object;
|
|
}
|
|
|
|
public static String convertTimesForSmartMoviePanel(String s) {
|
|
StringBuffer sBuff = new StringBuffer();
|
|
StringTokenizer sTok = new StringTokenizer(s, ",");
|
|
while (sTok.hasMoreTokens()) {
|
|
sBuff.append(String.valueOf(new Float(Float.parseFloat(sTok.nextToken()) * 1000).intValue()));
|
|
sBuff.append(',');
|
|
}
|
|
return sBuff.toString();
|
|
}
|
|
|
|
public void configure(String url) {
|
|
try {
|
|
SAXBuilder builder = new SAXBuilder();
|
|
Document cDoc = builder.build(new URL(url));
|
|
Element cRoot = cDoc.getRootElement();
|
|
Iterator it;
|
|
List tagOptions = cRoot.getChildren("tag");
|
|
if (tagOptions.size() > 0) {
|
|
tagInfo = new XMLTagInfo();
|
|
it = tagOptions.iterator();
|
|
while (it.hasNext()) {
|
|
Element e = (Element)it.next();
|
|
tagInfo.addTag(e.getAttributeValue("name"), new Boolean(e.getAttributeValue("visible")),
|
|
new Boolean(e.getAttributeValue("visiblecontents")), e.getAttributeValue("displayas"));
|
|
List atts = e.getChildren("attribute");
|
|
Iterator it2 = atts.iterator();
|
|
while (it2.hasNext()) {
|
|
Element eAtt = (Element)it2.next();
|
|
tagInfo.addAttribute(eAtt.getAttributeValue("name"), e.getAttributeValue("name"),
|
|
new Boolean(eAtt.getAttributeValue("visible")), eAtt.getAttributeValue("displayas"));
|
|
}
|
|
}
|
|
}
|
|
List parameters = cRoot.getChildren("parameter");
|
|
textConfig = new Properties();
|
|
config = new Properties();
|
|
it = parameters.iterator();
|
|
while (it.hasNext()) {
|
|
Element e = (Element)it.next();
|
|
String type = e.getAttributeValue("type");
|
|
if (type == null || type.equals("xpath"))
|
|
config.put(e.getAttributeValue("name"), e.getAttributeValue("val"));
|
|
else if (type.equals("text"))
|
|
textConfig.put(e.getAttributeValue("name"), e.getAttributeValue("val"));
|
|
}
|
|
rootElement = textConfig.getProperty("qd.root.element");
|
|
List navigations = cRoot.getChildren("navigation");
|
|
final String[] navigXPath = new String[navigations.size()];
|
|
configMenus = new JMenu[2];
|
|
configMenus[1] = new JMenu(messages.getString("View"));
|
|
it = navigations.iterator();
|
|
while (it.hasNext()) {
|
|
Element e = (Element)it.next();
|
|
final JMenuItem mItem = new JMenuItem(e.getAttributeValue("name"));
|
|
final String xpathExpression = e.getAttributeValue("val");
|
|
final String command = e.getAttributeValue("command");
|
|
mItem.setToolTipText(e.getChildTextNormalize("desc"));
|
|
mItem.setAccelerator(KeyStroke.getKeyStroke(e.getAttributeValue("keystroke")));
|
|
mItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
if (xpathExpression != null) {
|
|
editor.fireEndEditEvent();
|
|
boolean keepSearching;
|
|
JTextPane t = editor.getTextPane();
|
|
int offset = t.getCaret().getMark();
|
|
Object context = editor.getNodeForOffset(offset);
|
|
System.out.println("xpath--"+String.valueOf(offset)+": "+context.toString());
|
|
do {
|
|
keepSearching = false;
|
|
if (context != null) {
|
|
Object moveTo = XMLUtilities.findSingleNode(context, xpathExpression);
|
|
int newStartOffset = editor.getStartOffsetForNode(moveTo);
|
|
if (newStartOffset > -1) {
|
|
t.requestFocus();
|
|
t.setCaretPosition(newStartOffset);
|
|
} else {
|
|
keepSearching = true; //search again
|
|
context = moveTo;
|
|
}
|
|
}
|
|
} while (keepSearching);
|
|
if (command.equals("playNode")) {
|
|
Object nearestParent = XMLUtilities.findSingleNode(editor.getNodeForOffset(t.getCaret().getMark()), config.getProperty("qd.nearestplayableparent"));
|
|
playNode(nearestParent);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
configMenus[1].add(mItem);
|
|
}
|
|
configMenus[0] = new JMenu(messages.getString("Edit"));
|
|
if (editURL != null) try {
|
|
final Transformer transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(editURL));
|
|
List transformations = cRoot.getChildren("transformation");
|
|
it = transformations.iterator();
|
|
while (it.hasNext()) {
|
|
Element e = (Element)it.next();
|
|
final JMenuItem mItem = new JMenuItem(e.getAttributeValue("name"));
|
|
final String tasks = e.getAttributeValue("tasks");
|
|
final String nodeSelector = e.getAttributeValue("node");
|
|
final DOMOutputter domOut = new DOMOutputter();
|
|
final DOMBuilder jdomBuild = new DOMBuilder();
|
|
mItem.setToolTipText(e.getChildTextNormalize("desc"));
|
|
mItem.setAccelerator(KeyStroke.getKeyStroke(e.getAttributeValue("keystroke")));
|
|
mItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
try {
|
|
editor.fireEndEditEvent();
|
|
editor.setEditabilityTracker(false);
|
|
int offset = editor.getTextPane().getCaret().getMark();
|
|
Object context = editor.getNodeForOffset(offset);
|
|
Object transformNode = XMLUtilities.findSingleNode(context, nodeSelector);
|
|
if (!(transformNode instanceof Element)) return;
|
|
Element jdomEl = (Element)transformNode;
|
|
Element clone = (Element)jdomEl.clone();
|
|
Element cloneOwner = new Element("CloneOwner");
|
|
cloneOwner.addContent(clone);
|
|
org.w3c.dom.Element transformElement = domOut.output((Element)cloneOwner);
|
|
//String refreshID = XMLUtilities.getTextForNode(XMLUtilities.findSingleNode(context, config.getProperty("qd.refreshid")));
|
|
Enumeration enum = config.propertyNames();
|
|
while (enum.hasMoreElements()) {
|
|
String key = (String)enum.nextElement();
|
|
String val = config.getProperty(key);
|
|
if (!key.startsWith("qd.")) {
|
|
Object obj = XMLUtilities.findSingleNode(context, val);
|
|
if (obj != null) {
|
|
String id = XMLUtilities.getTextForNode(obj);
|
|
transformer.setParameter(key, id);
|
|
System.out.println("key="+key+" & id="+id);
|
|
}
|
|
}
|
|
}
|
|
enum = textConfig.propertyNames();
|
|
while (enum.hasMoreElements()) {
|
|
String key = (String)enum.nextElement();
|
|
transformer.setParameter(key, textConfig.getProperty(key));
|
|
}
|
|
float inSeconds = tcp.getInTime().floatValue() / 1000; //convert from milliseconds
|
|
float outSeconds = tcp.getOutTime().floatValue() / 1000; //convert from milliseconds
|
|
if (outSeconds >= inSeconds) { //time parameters will not be passed if out precedes in
|
|
transformer.setParameter("qd.start", String.valueOf(inSeconds));
|
|
transformer.setParameter("qd.end", String.valueOf(outSeconds));
|
|
System.out.println("Start="+String.valueOf(inSeconds)+" & End="+String.valueOf(outSeconds));
|
|
} else {
|
|
transformer.setParameter("qd.start", "");
|
|
transformer.setParameter("qd.end", "");
|
|
}
|
|
transformer.setParameter("qd.task", tasks);
|
|
|
|
JDOMResult jdomResult = new JDOMResult();
|
|
//DOMSource domSource = new DOMSource(docBuilder.newDocument());
|
|
//domSource.getNode().appendChild(transformElement);
|
|
//if (transformElement.getParentNode() == null)
|
|
// System.out.println("null parent");
|
|
DOMSource domSource = new DOMSource(transformElement);
|
|
//if (domSource == null)
|
|
// System.out.println("dom source is null");
|
|
transformer.transform(domSource, jdomResult);
|
|
Element transformedRoot = jdomResult.getDocument().getRootElement();
|
|
List replaceNodeWith = transformedRoot.getContent();
|
|
|
|
XMLOutputter xmlOut = new XMLOutputter();
|
|
try {
|
|
Element ee = (Element)cloneOwner;
|
|
xmlOut.output(ee, System.out);
|
|
xmlOut.output(jdomResult.getDocument(), System.out);
|
|
} catch (IOException ioe) {}
|
|
|
|
int start = editor.getStartOffsetForNode(transformNode);
|
|
int end = editor.getEndOffsetForNode(transformNode);
|
|
StyledDocument tDoc = editor.getTextPane().getStyledDocument();
|
|
AttributeSet attSet = tDoc.getCharacterElement(start).getAttributes();
|
|
float indent = StyleConstants.getLeftIndent(attSet);
|
|
try {
|
|
tDoc.insertString(end, "\n", null);
|
|
tDoc.remove(start, end-start);
|
|
//tDoc.insertString(PUT A CARRIAGE RETURN HERE... FOR TEXT)
|
|
} catch (BadLocationException ble) {
|
|
ble.printStackTrace();
|
|
return;
|
|
}
|
|
|
|
int insertPos = start;
|
|
Element el = (Element)transformNode;
|
|
if (el.isRootElement()) {
|
|
Iterator replaceIter = replaceNodeWith.iterator();
|
|
while (replaceIter.hasNext()) {
|
|
Object o = replaceIter.next();
|
|
if (o instanceof Element) {
|
|
replaceIter.remove();
|
|
Document d = el.getDocument();
|
|
d.detachRootElement();
|
|
Element er = (Element)o;
|
|
d.setRootElement(er);
|
|
editor.removeNode(er);
|
|
insertPos = editor.renderElement(er, indent, insertPos);
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
List parentContent = el.getParent().getContent(); //this is a live list
|
|
int elPos = parentContent.indexOf(el);
|
|
parentContent.remove(elPos);
|
|
editor.removeNode(transformNode);
|
|
Iterator replaceIter = replaceNodeWith.iterator();
|
|
while (replaceIter.hasNext()) {
|
|
Object next = replaceIter.next();
|
|
replaceIter.remove();
|
|
if (next instanceof Element) {
|
|
Element elem = (Element)next;
|
|
insertPos = editor.renderElement(elem, indent, insertPos);
|
|
} else if (next instanceof Text) {
|
|
Text text = (Text)next;
|
|
if (text.getTextTrim().length() > 0)
|
|
insertPos = editor.renderText(text, indent, insertPos);
|
|
}
|
|
parentContent.add(elPos, next);
|
|
elPos++;
|
|
}
|
|
}
|
|
|
|
try {
|
|
tDoc.remove(insertPos, 1); //removes extra dummy new line inserted above to protect indentation
|
|
String s = tDoc.getText(insertPos-1, 2);
|
|
if (s.charAt(1)=='\n') {
|
|
if (s.charAt(0)=='\n') {
|
|
tDoc.remove(insertPos-1, 1); //if two newlines, delete first
|
|
AttributeSet attSet2 = tDoc.getCharacterElement(insertPos-2).getAttributes();
|
|
tDoc.setCharacterAttributes(insertPos-1, 1, attSet2, false);
|
|
} else {
|
|
AttributeSet attSet2 = tDoc.getCharacterElement(insertPos-1).getAttributes();
|
|
tDoc.setCharacterAttributes(insertPos, 1, attSet2, false);
|
|
}
|
|
System.out.println("carriage return detected");
|
|
}
|
|
} catch (BadLocationException ble) {
|
|
ble.printStackTrace();
|
|
return;
|
|
}
|
|
|
|
editor.fixOffsets();
|
|
view.refresh();
|
|
hp.refresh();
|
|
player.initForSavant(convertTimesForSmartMoviePanel(view.getT1s()), convertTimesForSmartMoviePanel(view.getT2s()), view.getIDs());
|
|
|
|
transformer.clearParameters();
|
|
|
|
editor.setEditabilityTracker(true);
|
|
} catch (TransformerException tre) {
|
|
tre.printStackTrace();
|
|
} catch (JDOMException jdome) {
|
|
jdome.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
configMenus[0].add(mItem);
|
|
}
|
|
} catch (TransformerException tre) {
|
|
tre.printStackTrace();
|
|
}
|
|
} catch (JDOMException jdome) {
|
|
jdome.printStackTrace();
|
|
} catch (MalformedURLException murle) {
|
|
murle.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public JMenu[] getConfiguredMenus() {
|
|
return configMenus;
|
|
}
|
|
}
|
|
|
|
/*
|
|
private final static JskadKeyboardManager keybdMgr
|
|
= new JskadKeyboardManager(JskadKeyboardFactory.getAllAvailableJskadKeyboards());
|
|
protected JskadKeyboard activeKeyboard = null;
|
|
protected JskadKeyboard wylieKeyboard;
|
|
|
|
import org.jdom.output.XMLOutputter;
|
|
import org.jdom.transform.JDOMSource;
|
|
import javax.xml.transform.stream.*;
|
|
import javax.xml.transform.*;
|
|
|
|
|
|
public void changeKeyboard(JskadKeyboard kbd) {
|
|
activeKeyboard = kbd;
|
|
DuffPane dp = (DuffPane)pane;
|
|
activeKeyboard.activate(dp);
|
|
activeKeyboard.activate(sharedDP);
|
|
activeKeyboard.activate(sharedDP2);
|
|
}
|
|
|
|
public int findNextText(int startPos, StyledDocument sourceDoc, StyledDocument findDoc) {
|
|
if (startPos<0 || startPos>sourceDoc.getLength()-1)
|
|
return -1;
|
|
|
|
try {
|
|
|
|
AttributeSet firstAttr = findDoc.getCharacterElement(0).getAttributes();
|
|
String firstFontName = StyleConstants.getFontFamily(firstAttr);
|
|
char firstSearchChar = findDoc.getText(0,1).charAt(0);
|
|
|
|
boolean match = false;
|
|
for (int i=startPos; i<sourceDoc.getLength()-findDoc.getLength(); i++) {
|
|
AttributeSet attr = sourceDoc.getCharacterElement(i).getAttributes();
|
|
String fontName = StyleConstants.getFontFamily(attr);
|
|
char c = sourceDoc.getText(i,1).charAt(0);
|
|
|
|
if (c == firstSearchChar && fontName.equals(firstFontName)) { //found first character, now check subsequents
|
|
match = true;
|
|
for (int k=1; k<findDoc.getLength() && match; k++) {
|
|
if (findDoc.getText(k,1).charAt(0) == sourceDoc.getText(i+k,1).charAt(0)) {
|
|
AttributeSet attr2 = findDoc.getCharacterElement(k).getAttributes();
|
|
attr = sourceDoc.getCharacterElement(i+k).getAttributes();
|
|
if (!StyleConstants.getFontFamily(attr).equals(StyleConstants.getFontFamily(attr2)))
|
|
match = false;
|
|
} else
|
|
match = false;
|
|
}
|
|
if (match)
|
|
return i;
|
|
}
|
|
}
|
|
} catch (BadLocationException ble) {
|
|
ble.printStackTrace();
|
|
ThdlDebug.noteIffyCode();
|
|
}
|
|
|
|
return -1; //not found
|
|
}
|
|
|
|
public void findText() {
|
|
//get input from user on what to search for
|
|
JPanel p0 = new JPanel(new GridLayout(0,1));
|
|
JPanel p2 = new JPanel();
|
|
p2.add(new JLabel(messages.getString("FindWhat") + " "));
|
|
if (findDoc == null) {
|
|
sharedDP.setText("");
|
|
findDoc = (TibetanDocument)sharedDP.getDocument();
|
|
} else
|
|
sharedDP.setDocument(findDoc);
|
|
sharedDP.setPreferredSize(new Dimension(250,50));
|
|
p2.add(sharedDP);
|
|
p0.add(p2);
|
|
|
|
if (JOptionPane.showConfirmDialog(textFrame, p0, messages.getString("FindHeading"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) == JOptionPane.OK_OPTION) {
|
|
|
|
try {
|
|
TibetanDocument doc = (TibetanDocument)pane.getDocument();
|
|
Position pos = doc.createPosition(pane.getCaretPosition());
|
|
|
|
boolean startingOver = false;
|
|
int i=pos.getOffset();
|
|
while (true) {
|
|
i = findNextText(i, doc, findDoc);
|
|
if (i>0) { //found!! so highlight text and seek video
|
|
if (startingOver && i>pos.getOffset()-1)
|
|
break;
|
|
pane.setSelectionStart(i);
|
|
pane.setSelectionEnd(i+findDoc.getLength());
|
|
if (JOptionPane.showInternalConfirmDialog(textFrame, messages.getString("FindNextYesNo"), null, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) != JOptionPane.YES_OPTION)
|
|
break;
|
|
i++;
|
|
}
|
|
if (i<0 || i==doc.getLength() && pos.getOffset()>0) { //reached end of document - start over?
|
|
if (startingOver || pos.getOffset()==0)
|
|
break;
|
|
if (JOptionPane.showInternalConfirmDialog(textFrame, messages.getString("StartFromBeginning"), null, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) != JOptionPane.YES_OPTION)
|
|
break;
|
|
i=0;
|
|
startingOver = true;
|
|
}
|
|
}
|
|
} catch (BadLocationException ble) {
|
|
ble.printStackTrace();
|
|
ThdlDebug.noteIffyCode();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public void replaceText() {
|
|
//get input from user on what to search for
|
|
JPanel p0 = new JPanel(new GridLayout(0,1));
|
|
JPanel p2 = new JPanel();
|
|
p2.add(new JLabel(messages.getString("FindWhat") + " "));
|
|
if (findDoc == null) {
|
|
sharedDP.setText("");
|
|
findDoc = (TibetanDocument)sharedDP.getDocument();
|
|
} else
|
|
sharedDP.setDocument(findDoc);
|
|
sharedDP.setPreferredSize(new Dimension(250,50));
|
|
p2.add(sharedDP);
|
|
JPanel p3 = new JPanel();
|
|
p3.add(new JLabel(messages.getString("ReplaceWith") + " "));
|
|
if (replaceDoc == null) {
|
|
sharedDP2.setText("");
|
|
replaceDoc = (TibetanDocument)sharedDP2.getDocument();
|
|
} else
|
|
sharedDP2.setDocument(replaceDoc);
|
|
sharedDP2.setPreferredSize(new Dimension(250,50));
|
|
p3.add(sharedDP2);
|
|
|
|
p0.add(p2);
|
|
p0.add(p3);
|
|
|
|
if (JOptionPane.showConfirmDialog(textFrame, p0, messages.getString("FindReplaceHeading"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) == JOptionPane.OK_OPTION) {
|
|
|
|
try {
|
|
java.util.List replaceDCs = new ArrayList();
|
|
for (int k=0; k<replaceDoc.getLength(); k++)
|
|
replaceDCs.add(new DuffCode(TibetanMachineWeb.getTMWFontNumber(StyleConstants.getFontFamily(replaceDoc.getCharacterElement(k).getAttributes())), replaceDoc.getText(k,1).charAt(0)));
|
|
DuffData[] dd = TibTextUtils.convertGlyphs(replaceDCs);
|
|
|
|
TibetanDocument doc = (TibetanDocument)pane.getDocument();
|
|
Position pos = doc.createPosition(pane.getCaretPosition());
|
|
|
|
String[] replaceOptions = new String[3];
|
|
replaceOptions[0] = new String(messages.getString("Replace"));
|
|
replaceOptions[1] = new String(messages.getString("ReplaceAll"));
|
|
replaceOptions[2] = new String(messages.getString("NoReplace"));
|
|
|
|
boolean startingOver = false;
|
|
boolean replaceAll = false;
|
|
int i=pos.getOffset();
|
|
outer:
|
|
while (true) {
|
|
i = findNextText(i, doc, findDoc);
|
|
if (i>0) { //found!! so highlight text and seek video
|
|
if (startingOver && i>pos.getOffset()-1)
|
|
break;
|
|
if (replaceAll) {
|
|
doc.remove(i,findDoc.getLength());
|
|
doc.insertDuff(i,dd);
|
|
} else {
|
|
pane.setSelectionStart(i);
|
|
pane.setSelectionEnd(i+findDoc.getLength());
|
|
String choice = (String)JOptionPane.showInternalInputDialog(textFrame, messages.getString("ReplaceQ"), null, JOptionPane.PLAIN_MESSAGE, null, replaceOptions, replaceOptions[0]);
|
|
if (choice == null) //cancel, so stop searching
|
|
break outer;
|
|
if (choice.equals(replaceOptions[0])) { //replace
|
|
doc.remove(i,findDoc.getLength());
|
|
doc.insertDuff(i,dd);
|
|
}
|
|
else if (choice.equals(replaceOptions[1])) { //replace all
|
|
doc.remove(i,findDoc.getLength());
|
|
doc.insertDuff(i,dd);
|
|
replaceAll = true;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
if (i<0 || i==doc.getLength() && pos.getOffset()>0) { //reached end of document - start over?
|
|
if (startingOver || pos.getOffset()==0)
|
|
break;
|
|
if (JOptionPane.showInternalConfirmDialog(textFrame, messages.getString("StartFromBeginning"), null, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) != JOptionPane.YES_OPTION)
|
|
break;
|
|
i=0;
|
|
startingOver = true;
|
|
}
|
|
}
|
|
} catch (BadLocationException ble) {
|
|
ble.printStackTrace();
|
|
ThdlDebug.noteIffyCode();
|
|
}
|
|
|
|
}
|
|
}
|
|
*/
|