Savant and QuillDriver are being removed from THDL Tools
and moved to a new site: Tools for Field Linguistics.
This commit is contained in:
parent
4dff3b4ae0
commit
6cc0c5e99b
19 changed files with 0 additions and 4342 deletions
|
@ -1,415 +0,0 @@
|
|||
/*
|
||||
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.media;
|
||||
|
||||
import java.util.*;
|
||||
import java.net.*;
|
||||
import javax.media.*;
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
import org.thdl.util.ThdlDebug;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public class SmartJMFPlayer extends SmartMoviePanel implements ControllerListener
|
||||
{
|
||||
public URL mediaURL;
|
||||
|
||||
private Player player = null;
|
||||
private Component visualComponent = null;
|
||||
private Component controlComponent = null;
|
||||
private Panel panel = null;
|
||||
private JPanel vPanel = null;
|
||||
|
||||
private Container parent = null;
|
||||
|
||||
private java.util.Timer timer = null;
|
||||
private Time stopTime = null;
|
||||
private Time pauseTime = null;
|
||||
|
||||
private boolean isMediaAudio = false;
|
||||
private boolean isSized = false;
|
||||
|
||||
private boolean isRealized = false;
|
||||
private boolean isCached = false;
|
||||
|
||||
private Float to = null;
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public String getIdentifyingName() {
|
||||
return "Java Media Framework";
|
||||
}
|
||||
public URL getMediaURL() {
|
||||
return mediaURL;
|
||||
}
|
||||
public SmartJMFPlayer() {
|
||||
super(new GridLayout());
|
||||
}
|
||||
public SmartJMFPlayer(Container p, URL sound) throws SmartMoviePanelException {
|
||||
super( new GridLayout() );
|
||||
parent = p;
|
||||
loadMovie(sound);
|
||||
}
|
||||
public void loadMovie(URL sound) throws SmartMoviePanelException {
|
||||
if (mediaURL != null) {
|
||||
cmd_stop();
|
||||
destroy();
|
||||
}
|
||||
mediaURL = sound;
|
||||
start();
|
||||
}
|
||||
public void setParentContainer(Container c) {
|
||||
parent = c;
|
||||
}
|
||||
public void destroy() throws SmartMoviePanelException {
|
||||
if (false)
|
||||
throw new SmartMoviePanelException();
|
||||
removeAllAnnotationPlayers();
|
||||
player.close();
|
||||
removeAll();
|
||||
mediaURL = null;
|
||||
isRealized = false;
|
||||
isSized = false;
|
||||
visualComponent = null;
|
||||
controlComponent = null;
|
||||
panel = null;
|
||||
vPanel = null;
|
||||
isMediaAudio = false;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
private void start() {
|
||||
try {
|
||||
player = Manager.createPlayer(mediaURL);
|
||||
player.addControllerListener(this);
|
||||
} catch (javax.media.NoPlayerException e) {
|
||||
System.err.println("noplayer exception");
|
||||
e.printStackTrace();
|
||||
ThdlDebug.noteIffyCode();
|
||||
return;
|
||||
} catch (java.io.IOException ex) {
|
||||
System.err.println("IO exception");
|
||||
ex.printStackTrace();
|
||||
ThdlDebug.noteIffyCode();
|
||||
return;
|
||||
}
|
||||
if (player != null) {
|
||||
//player.realize();
|
||||
player.prefetch();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public void displayBorders(boolean borders) throws SmartMoviePanelException
|
||||
{
|
||||
if (false)
|
||||
throw new SmartMoviePanelException();
|
||||
}
|
||||
public void displayController(boolean controller) throws SmartMoviePanelException
|
||||
{
|
||||
if (false)
|
||||
throw new SmartMoviePanelException();
|
||||
|
||||
}
|
||||
public boolean isInitialized() {
|
||||
return isSized;
|
||||
}
|
||||
//public Dimension getSize() {
|
||||
// return player.getControlPanelComponent().getSize(); //tester avant si player exist
|
||||
//}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
private void showMediaComponent() {
|
||||
if (isRealized && isCached) {
|
||||
if (visualComponent == null) {
|
||||
if (panel == null) {
|
||||
setLayout(new GridLayout(1,1));
|
||||
vPanel = new JPanel();
|
||||
vPanel.setLayout( new BorderLayout() );
|
||||
if ((visualComponent = player.getVisualComponent())!= null)
|
||||
vPanel.add("Center", visualComponent);
|
||||
else
|
||||
isMediaAudio = true;
|
||||
if ((controlComponent = player.getControlPanelComponent()) != null) {
|
||||
if (visualComponent == null) //no video
|
||||
vPanel.setPreferredSize(new Dimension(400,25));
|
||||
vPanel.add("South", controlComponent);
|
||||
}
|
||||
}
|
||||
add(vPanel);
|
||||
parent.invalidate();
|
||||
parent.validate();
|
||||
parent.repaint();
|
||||
isSized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public synchronized void controllerUpdate(ControllerEvent event) {
|
||||
if (player == null)
|
||||
return;
|
||||
if (event instanceof RealizeCompleteEvent) {
|
||||
System.out.println("received RealizeCompleteEvent event");
|
||||
isRealized = true;
|
||||
if (mediaURL.getProtocol().equals("file")) { //if http then wait until entire media is cached
|
||||
isCached = true;
|
||||
showMediaComponent();
|
||||
} else if (isCached) //must be http
|
||||
showMediaComponent();
|
||||
} else if (event instanceof StartEvent) {
|
||||
System.out.println("received StartEvent event");
|
||||
launchAnnotationTimer(); //FIXME should have upper limit (stop time)
|
||||
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
timer = new java.util.Timer(true);
|
||||
timer.schedule(new TimerTask() {
|
||||
public void run() {
|
||||
//this is specifically for the MPG stop time bug
|
||||
if (stopTime != null)
|
||||
if (player.getMediaTime().getNanoseconds() > stopTime.getNanoseconds())
|
||||
player.stop();
|
||||
}}, 0, 15);
|
||||
} else if (event instanceof StopEvent) {
|
||||
pauseTime = player.getMediaTime();
|
||||
cancelAnnotationTimer();
|
||||
|
||||
/*messy problems require messy solutions:
|
||||
if the slider is present, dragging it while playing creates
|
||||
a RestartingEvent, and if I set the media time here it messes up
|
||||
and barely plays at all (maybe because it cancels the previously
|
||||
set media time? - I don't know).
|
||||
|
||||
but it seems that if you press the play/pause button on the
|
||||
control widget, then you need to set the media time upon stop
|
||||
(probably because of problem noted below, namely that you get
|
||||
weird results if you do player.start() without setting the media
|
||||
time.*/
|
||||
|
||||
if (!(event instanceof RestartingEvent)) {
|
||||
//player.setMediaTime(pauseTime);
|
||||
//player.prefetch();
|
||||
}
|
||||
|
||||
if (event instanceof StopAtTimeEvent) {
|
||||
System.out.println("received StopAtTimeEvent");
|
||||
} else if (event instanceof StopByRequestEvent) {
|
||||
System.out.println("received StopByRequestEvent");
|
||||
} else if (event instanceof RestartingEvent) {
|
||||
System.out.println("received RestartingEvent");
|
||||
} else if (event instanceof DataStarvedEvent) {
|
||||
System.out.println("received DataStarvedEvent");
|
||||
} else if (event instanceof DeallocateEvent) {
|
||||
System.out.println("received DeallocateEvent");
|
||||
} else if (event instanceof EndOfMediaEvent) {
|
||||
System.out.println("received EndOfMediaEvent");
|
||||
}
|
||||
|
||||
stopTime = null;
|
||||
|
||||
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
} else if (event instanceof CachingControlEvent) {
|
||||
CachingControlEvent cce = (CachingControlEvent)event;
|
||||
CachingControl cc = cce.getCachingControl();
|
||||
System.out.println("still caching at " + String.valueOf(cc.getContentProgress()));
|
||||
if (!(cc.getContentLength() > cc.getContentProgress())) {
|
||||
System.out.println("caching done!!");
|
||||
isCached = true;
|
||||
if (isRealized)
|
||||
showMediaComponent();
|
||||
}
|
||||
} else if (event instanceof ControllerErrorEvent) {
|
||||
player = null;
|
||||
System.err.println("*** ControllerErrorEvent *** " + ((ControllerErrorEvent)event).getMessage());
|
||||
} else if (event instanceof PrefetchCompleteEvent) {
|
||||
if (panel != null) {
|
||||
panel.invalidate();
|
||||
}
|
||||
parent.invalidate();
|
||||
parent.validate();
|
||||
parent.repaint();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public void cmd_stop() throws SmartMoviePanelException {
|
||||
if (player == null)
|
||||
throw new SmartMoviePanelException("no player");
|
||||
try {
|
||||
player.stop();
|
||||
} catch (NotRealizedError err) {
|
||||
throw new SmartMoviePanelException("JMF player not realized");
|
||||
}
|
||||
}
|
||||
public void cmd_playOn() throws SmartMoviePanelException {
|
||||
if (player == null) {
|
||||
throw new SmartMoviePanelException("no player or video still loading");
|
||||
}
|
||||
if (player.getState() == Controller.Started)
|
||||
return;
|
||||
|
||||
if (pauseTime == null)
|
||||
player.setMediaTime(new Time(0.0));
|
||||
else
|
||||
player.setMediaTime(pauseTime);
|
||||
if (player.getTargetState() < Player.Started) {
|
||||
player.setStopTime(Clock.RESET);
|
||||
player.prefetch();
|
||||
}
|
||||
player.start();
|
||||
}
|
||||
public void cmd_playSegment(Integer from, Integer to) throws SmartMoviePanelException {
|
||||
if (from == null || player == null)
|
||||
throw new SmartMoviePanelException("no player or video still loading");
|
||||
|
||||
final Time startTime = new Time(from.longValue() * 1000000);
|
||||
try {
|
||||
if (player.getState() == Controller.Started)
|
||||
player.stop();
|
||||
while (player.getState() == Controller.Unrealized)
|
||||
;
|
||||
if (to == null) {
|
||||
stopTime = null;
|
||||
player.setStopTime(Clock.RESET);
|
||||
} else {
|
||||
stopTime = new Time(to.longValue() * 1000000);
|
||||
player.setStopTime(stopTime);
|
||||
}
|
||||
player.setMediaTime(startTime);
|
||||
player.prefetch();
|
||||
player.start();
|
||||
} catch(NotRealizedError err) {
|
||||
throw new SmartMoviePanelException("JMF player not realized");
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public boolean isPlaying() {
|
||||
if (player == null)
|
||||
return false;
|
||||
if (player.getState() == Controller.Started)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
public int getCurrentTime() {
|
||||
if (player == null)
|
||||
return -1;
|
||||
if (player.getState() < Controller.Realized)
|
||||
return -1;
|
||||
long currTime = player.getMediaNanoseconds();
|
||||
return new Long(currTime / 1000000).intValue();
|
||||
}
|
||||
public int getEndTime() {
|
||||
Time t = player.getDuration();
|
||||
long l = t.getNanoseconds();
|
||||
return new Long(l / 1000000).intValue();
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
After pause the MPEG video and playing it again it gets faster
|
||||
Author: vladshtr
|
||||
In Reply To: After pause the MPEG video and playing it again it gets faster
|
||||
Mar 1, 2001 6:25 PM
|
||||
|
||||
Reply 1 of 1
|
||||
|
||||
|
||||
The problem is in the setting the Media time.
|
||||
|
||||
The safety way is to always set new media time with the
|
||||
following method: setMediaTime(Time time); .... if you want to
|
||||
use it after
|
||||
-player.stop(); used as real stop you can use setMediaTime(new
|
||||
Time(0.0));
|
||||
-player.stop(); used as real pause you have to use the
|
||||
combination:
|
||||
player.stop();
|
||||
Time currentTime = player.getMediaTime();
|
||||
//........
|
||||
player.setMediaTime(currentTime);
|
||||
player.start();
|
||||
|
||||
|
||||
Re: (urgent) when you pause and resume, video plays at rate > 1
|
||||
Author: seertenedos
|
||||
In Reply To: (urgent) when you pause and resume, video plays at rate > 1
|
||||
Aug 11, 2002 11:36 PM
|
||||
|
||||
Reply 1 of 1
|
||||
|
||||
|
||||
I found a solution for this problem for those that are interested.
|
||||
|
||||
what you have to do is store the time just before you pause and then set the
|
||||
time just before you play. here is a copy of my pause and play methods
|
||||
|
||||
// Start the player
|
||||
private void play() {
|
||||
if (player != null)
|
||||
{
|
||||
if (pauseTime != null)
|
||||
{
|
||||
player.setMediaTime(pauseTime);
|
||||
}
|
||||
if (player.getTargetState() < Player.Started)
|
||||
player.prefetch();
|
||||
player.start();
|
||||
}
|
||||
}
|
||||
|
||||
// Pause the player
|
||||
private void pause() {
|
||||
if (player != null)
|
||||
pauseTime = player.getMediaTime();
|
||||
player.stop();
|
||||
}
|
||||
|
||||
|
||||
that should solve your pause play problems!
|
||||
|
||||
> The problem is below. It seems quite a few people are
|
||||
> having this problem but i have not seen a solution
|
||||
> around. I really need a solution to this problem as
|
||||
> the whole point of my application is that it plays
|
||||
> divx and mpeg videos. At the moment i have divx
|
||||
> movies playing through the mpeg demuxer as the avi one
|
||||
> stuffed up the audio. I think that is the reason it
|
||||
> affects both divx and mpeg. My application is due in
|
||||
> one week and my client is not going to be very happy
|
||||
> if this problem happens every time they pause then
|
||||
> play the video.
|
||||
> The player is for divx movies. If anyone knows how to
|
||||
> solve this problem or how to make it so you can pause
|
||||
> and resume divx movies please respond.
|
||||
>
|
||||
> Pause and Resume playback.
|
||||
> The video plays at a high rate and there is no audio.
|
||||
> Problem doesn't appear while seeking.
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
|
||||
*/
|
||||
/* comments from michel
|
||||
I change the player.realise() to a player.prefetch() call at the end of the start function.
|
||||
*/
|
|
@ -1,298 +0,0 @@
|
|||
/*
|
||||
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.media;
|
||||
|
||||
import java.awt.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import javax.swing.event.EventListenerList;
|
||||
|
||||
import org.thdl.savant.AnnotationPlayer; //should move AP to org.thdl.annotation
|
||||
|
||||
|
||||
public abstract class SmartMoviePanel extends Panel
|
||||
{
|
||||
//fields
|
||||
private EventListenerList listenerList = new EventListenerList();
|
||||
|
||||
private Vector orderStartID = null, orderEndID = null;
|
||||
private Stack pileStart = null, pileEnd = null;
|
||||
private Hashtable hashStart = null, hashEnd = null;
|
||||
|
||||
private Timer annTimer = null;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public void addAnnotationPlayer(AnnotationPlayer ap)
|
||||
{
|
||||
listenerList.add(AnnotationPlayer.class, ap);
|
||||
}
|
||||
public void removeAnnotationPlayer(AnnotationPlayer ap)
|
||||
{
|
||||
listenerList.remove(AnnotationPlayer.class, ap);
|
||||
}
|
||||
public void removeAllAnnotationPlayers() {
|
||||
listenerList = new EventListenerList();
|
||||
}
|
||||
private void fireStartAnnotation(String id)
|
||||
{
|
||||
//see javadocs on EventListenerList for how following array is structured
|
||||
Object[] listeners = listenerList.getListenerList();
|
||||
|
||||
for (int i = listeners.length-2; i>=0; i-=2)
|
||||
{
|
||||
if (listeners[i]==AnnotationPlayer.class)
|
||||
((AnnotationPlayer)listeners[i+1]).startAnnotation(id);
|
||||
}
|
||||
}
|
||||
private void fireStopAnnotation(String id)
|
||||
{
|
||||
//see javadocs on EventListenerList for how following array is structured
|
||||
Object[] listeners = listenerList.getListenerList();
|
||||
|
||||
for (int i = listeners.length-2; i>=0; i-=2)
|
||||
{
|
||||
if (listeners[i]==AnnotationPlayer.class)
|
||||
((AnnotationPlayer)listeners[i+1]).stopAnnotation(id);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public void initForSavant(String starts, String ends, String ids) {
|
||||
String TAB_STARTS = starts;
|
||||
String TAB_ENDS = ends;
|
||||
String TAB_IDS = ids;
|
||||
|
||||
hashStart = new Hashtable();
|
||||
hashEnd = new Hashtable();
|
||||
pileStart = new Stack();
|
||||
pileEnd = new Stack();
|
||||
|
||||
StringTokenizer stIDS = new StringTokenizer(TAB_IDS, ",");
|
||||
StringTokenizer stSTARTS = new StringTokenizer(TAB_STARTS, ",");
|
||||
StringTokenizer stENDS = new StringTokenizer(TAB_ENDS, ",");
|
||||
while ((stIDS.hasMoreTokens()) && (stSTARTS.hasMoreTokens()) && (stENDS.hasMoreTokens())) {
|
||||
String sID = stIDS.nextToken();
|
||||
String sStart = stSTARTS.nextToken();
|
||||
String sEnd = stENDS.nextToken();
|
||||
try {
|
||||
Integer start = new Integer(sStart);
|
||||
hashStart.put(sID, start);
|
||||
} catch (NumberFormatException err) {
|
||||
hashStart.put(sID, new Integer(0));
|
||||
}
|
||||
try {
|
||||
Integer end = new Integer(sEnd);
|
||||
hashEnd.put(sID, end);
|
||||
} catch (NumberFormatException err) {
|
||||
hashEnd.put(sID, new Integer(0));
|
||||
}
|
||||
}
|
||||
|
||||
Vector saveOrder = new Vector();
|
||||
for (Enumeration e = hashStart.keys() ; e.hasMoreElements() ;) {
|
||||
Object o = e.nextElement();
|
||||
saveOrder.addElement(o);
|
||||
}
|
||||
orderStartID = new Vector();
|
||||
while (saveOrder.size() > 0) {
|
||||
int num = getMinusStart(saveOrder);
|
||||
orderStartID.addElement(saveOrder.elementAt(num));
|
||||
saveOrder.removeElementAt(num);
|
||||
}
|
||||
saveOrder = new Vector();
|
||||
for (Enumeration e = hashEnd.keys() ; e.hasMoreElements() ;) {
|
||||
Object o = e.nextElement();
|
||||
saveOrder.addElement(o);
|
||||
}
|
||||
orderEndID = new Vector();
|
||||
while (saveOrder.size() > 0) {
|
||||
int num = getMinusEnd(saveOrder);
|
||||
orderEndID.addElement(saveOrder.elementAt(num));
|
||||
saveOrder.removeElementAt(num);
|
||||
}
|
||||
}
|
||||
public String cmd_firstS() {
|
||||
return (String)orderStartID.elementAt(0);
|
||||
}
|
||||
private int getMinusStart(Vector v) {
|
||||
int index = 0;
|
||||
String first = (String)v.elementAt(index);
|
||||
Integer minus = (Integer)hashStart.get(first);
|
||||
for (int i=0;i<v.size();i++) {
|
||||
String s = (String)v.elementAt(i);
|
||||
Integer f = (Integer)hashStart.get(s);
|
||||
if (minus.intValue() > f.intValue()) {
|
||||
minus = f;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
private int getMinusEnd(Vector v) {
|
||||
int index = 0;
|
||||
String first = (String)v.elementAt(index);
|
||||
Integer minus = (Integer)hashEnd.get(first);
|
||||
for (int i=0;i<v.size();i++) {
|
||||
String s = (String)v.elementAt(i);
|
||||
Integer f = (Integer)hashEnd.get(s);
|
||||
if (minus.intValue() > f.intValue()) {
|
||||
minus = f;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
public boolean cmd_isID(String theID) {
|
||||
System.out.println(hashStart.containsKey(theID));
|
||||
return hashStart.containsKey(theID);
|
||||
}
|
||||
public void cmd_playFrom(String fromID) {
|
||||
Integer from = (Integer)hashStart.get(fromID);
|
||||
try {
|
||||
cmd_playSegment(from, null);
|
||||
} catch (SmartMoviePanelException smpe) {
|
||||
smpe.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void cmd_playS(String fromID) {
|
||||
Integer from = (Integer)hashStart.get(fromID);
|
||||
Integer to = (Integer)hashEnd.get(fromID);
|
||||
try {
|
||||
cmd_playSegment(from, to);
|
||||
} catch (SmartMoviePanelException smpe) {
|
||||
smpe.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void launchAnnotationTimer() { //FIXME: should have upper limit - stop time else end time
|
||||
if (listenerList.getListenerCount() == 0) //no annotation listeners
|
||||
return;
|
||||
|
||||
int i = getCurrentTime();
|
||||
Integer from = new Integer(i);
|
||||
remplisPileStart(from, new Integer(getEndTime()));
|
||||
if (annTimer != null) {
|
||||
annTimer.cancel();
|
||||
annTimer = null;
|
||||
}
|
||||
annTimer = new java.util.Timer(true);
|
||||
annTimer.schedule(new TimerTask() {
|
||||
public void run() {
|
||||
cmd_nextEvent();
|
||||
}}, 0, 15);
|
||||
}
|
||||
public void cancelAnnotationTimer() {
|
||||
if (listenerList.getListenerCount() == 0) //no annotation listeners
|
||||
return;
|
||||
|
||||
if (annTimer != null) {
|
||||
annTimer.cancel();
|
||||
annTimer = null;
|
||||
}
|
||||
}
|
||||
private void cmd_nextEvent() {
|
||||
Integer when = new Integer(getCurrentTime());
|
||||
if (!pileStart.empty()) {
|
||||
String id = (String)pileStart.peek();
|
||||
Integer f = (Integer)hashStart.get(id);
|
||||
if (when.intValue() >= f.intValue()) {
|
||||
id = (String)pileStart.pop();
|
||||
fireStartAnnotation(id);
|
||||
}
|
||||
}
|
||||
if (!pileEnd.empty()) {
|
||||
String id = (String)pileEnd.peek();
|
||||
Integer f = (Integer)hashEnd.get(id);
|
||||
if (when.intValue() >= f.intValue()) {
|
||||
id = (String)pileEnd.pop();
|
||||
fireStopAnnotation(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void vide_Pile() {
|
||||
while (!pileEnd.empty()) { //vider la pile des items qui ne sont pas
|
||||
String id = (String)pileEnd.pop(); //encore fini
|
||||
if (pileStart.search(id) == -1) {
|
||||
fireStopAnnotation(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* empties the pile, and then reconstructs it to consist of all ids
|
||||
whose start time or end time is included between start and end. */
|
||||
|
||||
private void remplisPileStart(Integer start, Integer end) {
|
||||
vide_Pile();
|
||||
pileStart.removeAllElements();
|
||||
pileEnd.removeAllElements();
|
||||
for (int i=orderEndID.size()-1; i!=-1; i--) {
|
||||
String id = (String)orderEndID.elementAt(i);
|
||||
Integer f = (Integer)hashEnd.get(id);
|
||||
if ((f.intValue() > start.intValue()) && (f.intValue() <= end.intValue())) {
|
||||
pileEnd.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
/* note: we are also interested in ids that begin before start,
|
||||
provided they overlap with the interval start-end. */
|
||||
|
||||
for (int i=orderStartID.size()-1; i!=-1; i--) {
|
||||
String id = (String)orderStartID.elementAt(i);
|
||||
Integer f = (Integer)hashStart.get(id);
|
||||
Integer f2 = (Integer)hashEnd.get(id);
|
||||
if ( (f.intValue() >= start.intValue() && f.intValue() < end.intValue()) ||
|
||||
(f.intValue() < start.intValue() && f2.intValue() > start.intValue())) {
|
||||
pileStart.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
//constructor
|
||||
public SmartMoviePanel(GridLayout layout)
|
||||
{
|
||||
super(layout);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
//abstract methods
|
||||
|
||||
|
||||
public abstract String getIdentifyingName();
|
||||
public abstract URL getMediaURL();
|
||||
public abstract void setParentContainer(Container c);
|
||||
|
||||
//helper methods - initialize
|
||||
public abstract void displayBorders(boolean borders) throws SmartMoviePanelException;
|
||||
public abstract void displayController(boolean controller) throws SmartMoviePanelException;
|
||||
public abstract void loadMovie(URL mediaUrl) throws SmartMoviePanelException;
|
||||
|
||||
//helper methods - control media
|
||||
public abstract void cmd_playOn() throws SmartMoviePanelException;
|
||||
public abstract void cmd_playSegment(Integer startTime, Integer stopTime) throws SmartMoviePanelException;
|
||||
public abstract void cmd_stop() throws SmartMoviePanelException;
|
||||
|
||||
//helper methods - media status
|
||||
public abstract boolean isInitialized();
|
||||
public abstract boolean isPlaying();
|
||||
public abstract int getCurrentTime();
|
||||
public abstract int getEndTime();
|
||||
|
||||
//helper methods - cleanup
|
||||
public abstract void destroy() throws SmartMoviePanelException;
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
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.media;
|
||||
|
||||
public class SmartMoviePanelException extends Exception
|
||||
{
|
||||
public SmartMoviePanelException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
public SmartMoviePanelException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
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.media;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.thdl.util.*;
|
||||
|
||||
import org.thdl.util.ThdlDebug;
|
||||
import org.thdl.util.OperatingSystemUtils;
|
||||
|
||||
public class SmartPlayerFactory {
|
||||
public static List moviePlayers;
|
||||
|
||||
/** You cannot instantiate this class. */
|
||||
private SmartPlayerFactory() { }
|
||||
|
||||
public static List getAllAvailableSmartPlayers() {
|
||||
String defaultPlayer, player;
|
||||
switch (OperatingSystemUtils.getOSType()) {
|
||||
case OperatingSystemUtils.MAC:
|
||||
//macs default to org.thdl.media.SmartQT4JPlayer
|
||||
defaultPlayer = "org.thdl.media.SmartQT4JPlayer";
|
||||
break;
|
||||
case OperatingSystemUtils.WIN32:
|
||||
//windows defaults to SmartJMFPlayer
|
||||
defaultPlayer = "org.thdl.media.SmartJMFPlayer";
|
||||
break;
|
||||
default:
|
||||
//put linux etc. here
|
||||
defaultPlayer = "org.thdl.media.SmartJMFPlayer";
|
||||
break;
|
||||
}
|
||||
|
||||
player
|
||||
= ThdlOptions.getStringOption("thdl.media.player", defaultPlayer);
|
||||
|
||||
|
||||
String[] possiblePlayers;
|
||||
if (player.equals("org.thdl.media.SmartJMFPlayer"))
|
||||
possiblePlayers = new String[] {"org.thdl.media.SmartJMFPlayer", "org.thdl.media.SmartQT4JPlayer"};
|
||||
else
|
||||
possiblePlayers = new String[] {"org.thdl.media.SmartQT4JPlayer", "org.thdl.media.SmartJMFPlayer"};
|
||||
|
||||
moviePlayers = new ArrayList();
|
||||
for (int i=0; i<possiblePlayers.length; i++) {
|
||||
try {
|
||||
Class mediaClass = Class.forName(possiblePlayers[i]);
|
||||
|
||||
//FIXME: playerClasses.add(mediaClass);
|
||||
|
||||
SmartMoviePanel smp = (SmartMoviePanel)mediaClass.newInstance();
|
||||
moviePlayers.add(smp);
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
System.out.println("No big deal: class " + possiblePlayers[i] + " not found.");
|
||||
} catch (LinkageError lie) {
|
||||
System.out.println("No big deal: class " + possiblePlayers[i] + " not found.");
|
||||
} catch (InstantiationException ie) {
|
||||
ie.printStackTrace();
|
||||
} catch (SecurityException se) {
|
||||
se.printStackTrace();
|
||||
} catch (IllegalAccessException iae) {
|
||||
iae.printStackTrace();
|
||||
ThdlDebug.noteIffyCode();
|
||||
}
|
||||
}
|
||||
return moviePlayers;
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
package org.thdl.media;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
import java.applet.*;
|
||||
import java.util.*;
|
||||
import java.net.*;
|
||||
import javax.media.*;
|
||||
import netscape.javascript.JSObject;
|
||||
import java.awt.*;
|
||||
import org.thdl.savant.AnnotationPlayer;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public class SmartQT4JApplet extends Applet implements AnnotationPlayer {
|
||||
|
||||
static public String FIC_SOUND;
|
||||
private SmartQT4JPlayer myPlayer;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public void init() {
|
||||
FIC_SOUND = getParameter("Sound");
|
||||
String TAB_STARTS = getParameter("STARTS");
|
||||
String TAB_ENDS = getParameter("ENDS");
|
||||
String TAB_IDS = getParameter("IDS");
|
||||
|
||||
myPlayer = new SmartQT4JPlayer();
|
||||
myPlayer.setParentContainer(this);
|
||||
myPlayer.initForSavant(convertTimesForSmartMoviePanel(TAB_STARTS), convertTimesForSmartMoviePanel(TAB_ENDS), TAB_IDS);
|
||||
myPlayer.addAnnotationPlayer(this);
|
||||
setLayout(new BorderLayout());
|
||||
add("Center", myPlayer);
|
||||
}
|
||||
public void destroy() {
|
||||
//why don't you send an exception
|
||||
//try {
|
||||
myPlayer.destroy();
|
||||
//} catch (SmartMoviePanelException e) {
|
||||
// System.out.println(e.getMessage());
|
||||
//}
|
||||
}
|
||||
public void start() {
|
||||
try {
|
||||
myPlayer.loadMovie(new URL(FIC_SOUND));
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public boolean cmd_isRealized() {
|
||||
return myPlayer.isInitialized();
|
||||
}
|
||||
public String cmd_firstS() {
|
||||
return myPlayer.cmd_firstS();
|
||||
}
|
||||
public boolean cmd_stop() {
|
||||
try {
|
||||
myPlayer.cmd_stop();
|
||||
return true;
|
||||
} catch (SmartMoviePanelException err) {
|
||||
System.out.println(err.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean cmd_isID(String theID) {
|
||||
return myPlayer.cmd_isID(theID);
|
||||
}
|
||||
public void cmd_playFrom(String fromID) {
|
||||
myPlayer.cmd_playFrom(fromID);
|
||||
}
|
||||
public void cmd_playS(String fromID) {
|
||||
myPlayer.cmd_playS(fromID);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public void startAnnotation(String id) {
|
||||
sendMessage("startplay", id);
|
||||
}
|
||||
public void stopAnnotation(String id) {
|
||||
sendMessage("endplay", id);
|
||||
}
|
||||
private void sendMessage(String method, String mess) {
|
||||
Object args[] = { mess };
|
||||
try {
|
||||
JSObject.getWindow(this).call(method, args);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Erreur appel javascript: "+e+" "+mess);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
private 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();
|
||||
}
|
||||
};
|
|
@ -1,284 +0,0 @@
|
|||
/*
|
||||
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.media;
|
||||
|
||||
import java.awt.*;
|
||||
import java.net.*;
|
||||
import quicktime.*;
|
||||
import quicktime.app.*;
|
||||
import quicktime.app.display.*;
|
||||
import quicktime.app.players.*;
|
||||
import quicktime.app.image.*; //required for the QT4JAVA test
|
||||
import quicktime.std.*;
|
||||
import quicktime.std.movies.*;
|
||||
import quicktime.std.movies.media.DataRef;
|
||||
import quicktime.io.*;
|
||||
import quicktime.app.time.*;
|
||||
import quicktime.std.clocks.*;
|
||||
import quicktime.app.QTFactory;
|
||||
|
||||
public class SmartQT4JPlayer extends SmartMoviePanel {
|
||||
|
||||
private myJumpCallBack theJumpper = null;
|
||||
private myRateCallBack theRater = null;
|
||||
private URL mediaUrl = null;
|
||||
private TimeBase myMoviesTimeBase;
|
||||
private QTCanvas canvas;
|
||||
private QTPlayer player;
|
||||
|
||||
//constructor
|
||||
public SmartQT4JPlayer(Container cont, URL mediaURL) {
|
||||
super( new GridLayout() );
|
||||
try {
|
||||
loadMovie(mediaURL);
|
||||
} catch (SmartMoviePanelException smpe) {
|
||||
smpe.printStackTrace();
|
||||
}
|
||||
}
|
||||
//destructor
|
||||
public void destroy() {
|
||||
if (theJumpper != null)
|
||||
theJumpper.cancelAndCleanup();
|
||||
if(theRater != null)
|
||||
theRater.cancelAndCleanup();
|
||||
|
||||
removeAllAnnotationPlayers();
|
||||
QTSession.close();
|
||||
removeAll();
|
||||
mediaUrl = null;
|
||||
System.out.println("Clean up performed.");
|
||||
}
|
||||
|
||||
//accessors
|
||||
public String getIdentifyingName() {
|
||||
return "Quicktime for Java";
|
||||
}
|
||||
public URL getMediaURL() {
|
||||
return mediaUrl;
|
||||
}
|
||||
public void setParentContainer(Container c) {
|
||||
}
|
||||
public void setPlayer(QTDrawable player) {
|
||||
this.player = (QTPlayer)player;
|
||||
}
|
||||
public QTPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
public void setCanvas(QTCanvas canvas) {
|
||||
this.canvas = canvas;
|
||||
}
|
||||
public QTCanvas getCanvas() {
|
||||
return canvas;
|
||||
}
|
||||
|
||||
|
||||
//contract methods - initialize
|
||||
public void displayBorders(boolean borders) throws SmartMoviePanelException {
|
||||
}
|
||||
public void displayController(boolean controller) throws SmartMoviePanelException {
|
||||
}
|
||||
|
||||
public void loadMovie(URL mediaURL) throws SmartMoviePanelException {
|
||||
//Initialize a QT session and add a test image
|
||||
|
||||
//These three try/catch blocks come from PlayMovie.java copyright
|
||||
// Apple Co. I'm using it to test that QT and QT4Java exist
|
||||
try {
|
||||
if (QTSession.isInitialized() == false) {
|
||||
QTSession.open();
|
||||
try {
|
||||
setCanvas( new QTCanvas(QTCanvas.kInitialSize, 0.5F, 0.5F) );
|
||||
this.add( getCanvas() );
|
||||
getCanvas().setClient(ImageDrawer.getQTLogo(), true);
|
||||
} catch(QTException qte) {
|
||||
qte.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (NoClassDefFoundError er) {
|
||||
add (new Label ("Can't Find QTJava classes"), "North");
|
||||
add (new Label ("Check install and try again"), "South");
|
||||
} catch (SecurityException se) {
|
||||
// this is thrown by MRJ trying to find QTSession class
|
||||
add (new Label ("Can't Find QTJava classes"), "North");
|
||||
add (new Label ("Check install and try again"), "South");
|
||||
} catch (Exception e) {
|
||||
// do a dynamic test for QTException
|
||||
//so the QTException class is not loaded unless
|
||||
// an unknown exception is thrown by the runtime
|
||||
if (e instanceof ClassNotFoundException || e instanceof java.io.FileNotFoundException) {
|
||||
add (new Label ("Can't Find QTJava classes"), "North");
|
||||
add (new Label ("Check install and try again"), "South");
|
||||
} else if (e instanceof QTException) {
|
||||
add (new Label ("Problem with QuickTime install"), "North");
|
||||
if (((QTException)e).errorCode() == -2093)
|
||||
add (new Label ("QuickTime must be installed"), "South");
|
||||
else
|
||||
add (new Label (e.getMessage()), "South");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
this.remove( getCanvas() );
|
||||
setPlayer(QTFactory.makeDrawable(mediaURL.toString()));
|
||||
getCanvas().setClient( getPlayer(), true );
|
||||
this.add( getCanvas() );
|
||||
System.out.println("loadMovie:"+mediaURL.toString());
|
||||
|
||||
myMoviesTimeBase = getPlayer().getTimeBase();
|
||||
theJumpper = new myJumpCallBack(myMoviesTimeBase);
|
||||
theJumpper.callMeWhen();
|
||||
theRater = new myRateCallBack(myMoviesTimeBase, 0, StdQTConstants.triggerRateChange);
|
||||
theRater.callMeWhen();
|
||||
Timer timer = new Timer(10,1,new Tickler(), getPlayer().getMovieController().getMovie());
|
||||
timer.setActive(true);
|
||||
} catch(QTException qte) {
|
||||
System.out.println("loadMovie failed");
|
||||
qte.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//contract methods - control media
|
||||
public void cmd_playOn() throws SmartMoviePanelException {
|
||||
try {
|
||||
getPlayer().setRate(1.0F);
|
||||
} catch(QTException qte) {
|
||||
qte.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void cmd_playSegment(Integer startTime, Integer stopTime) throws SmartMoviePanelException {
|
||||
try {
|
||||
int myScale = getPlayer().getScale();
|
||||
cmd_stop();
|
||||
getPlayer().setTime( (startTime.intValue() * myScale) / 1000 );
|
||||
|
||||
if (stopTime == null) {
|
||||
myMoviesTimeBase.setStopTime(new TimeRecord(myScale, getEndTime()));
|
||||
//System.out.println("startTime:"+(startTime.intValue()*myScale)/1000+" stopTime: to the End" );
|
||||
} else {
|
||||
myMoviesTimeBase.setStopTime(new TimeRecord(myScale, (stopTime.intValue()*myScale)/1000));
|
||||
//System.out.println("startTime:"+(startTime.intValue()*myScale)/1000+" stopTime:"+(stopTime.intValue()*myScale)/1000 );
|
||||
}
|
||||
cmd_playOn();
|
||||
}
|
||||
catch (SmartMoviePanelException smpe) {
|
||||
}
|
||||
catch (StdQTException sqte) {
|
||||
}
|
||||
catch (QTException qte) {
|
||||
}
|
||||
}
|
||||
public void cmd_stop() throws SmartMoviePanelException {
|
||||
try {
|
||||
getPlayer().setRate(0.0F);
|
||||
} catch(QTException qte) {
|
||||
qte.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//contract methods - media status
|
||||
public boolean isInitialized() {
|
||||
return true; //FIXME what should this do?
|
||||
}
|
||||
public boolean isPlaying() {
|
||||
try {
|
||||
if (player.getRate() > 0)
|
||||
return true;
|
||||
} catch (StdQTException stdqte) {
|
||||
stdqte.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//doit envoyer le temps en sec fois 1000
|
||||
public int getCurrentTime() {
|
||||
try {
|
||||
int myScale = getPlayer().getScale();
|
||||
//System.out.println("getCurrentTime():"+(player.getTime()*1000)/myScale);
|
||||
return (player.getTime()*1000)/myScale;
|
||||
} catch (StdQTException stqte) {
|
||||
stqte.printStackTrace();
|
||||
return 0;
|
||||
} catch (QTException qte) {
|
||||
System.out.println("getCurrentTimeErr");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public int getEndTime() {
|
||||
try {
|
||||
int myScale = getPlayer().getScale();
|
||||
return (player.getDuration()*1000)/myScale;
|
||||
} catch (StdQTException stqte) {
|
||||
stqte.printStackTrace();
|
||||
return 0;
|
||||
} catch (QTException qte) {
|
||||
System.out.println("getCurrentTimeErr");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public SmartQT4JPlayer() {
|
||||
super( new GridLayout() );
|
||||
}
|
||||
|
||||
// inner classes
|
||||
|
||||
|
||||
class myRateCallBack extends quicktime.std.clocks.RateCallBack {
|
||||
public myRateCallBack(TimeBase tb, int scale, int flag) throws QTException {
|
||||
super(tb, scale, flag);
|
||||
}
|
||||
public void execute() {
|
||||
try {
|
||||
//System.out.println("myRateCallBack: " + String.valueOf(rateWhenCalled));
|
||||
if (rateWhenCalled > 0)
|
||||
launchAnnotationTimer();
|
||||
else
|
||||
cancelAnnotationTimer();
|
||||
cancel();
|
||||
callMeWhen();
|
||||
} catch (Exception e) {
|
||||
System.out.println("myRateCallBack err: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
class myJumpCallBack extends quicktime.std.clocks.TimeJumpCallBack {
|
||||
public myJumpCallBack(TimeBase tb) throws QTException {
|
||||
super(tb);
|
||||
}
|
||||
public void execute() {
|
||||
try {
|
||||
//System.out.println("myJumpCallBack: " + String.valueOf(rateWhenCalled));
|
||||
if (rateWhenCalled > 0)
|
||||
launchAnnotationTimer();
|
||||
cancel();
|
||||
callMeWhen();
|
||||
} catch (Exception e) {
|
||||
System.out.println("myJumpCallBack err: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
public class Tickler implements Ticklish {
|
||||
public void timeChanged(int newTime) throws QTException {
|
||||
//System.out.println("*** TimerClass *** timeChanged at:"+newTime);
|
||||
}
|
||||
public boolean tickle(float er,int time) throws QTException {
|
||||
//System.out.println("*** TimerClass *** tickle at:"+time);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,24 +0,0 @@
|
|||
|
||||
/*
|
||||
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;
|
||||
|
||||
public class QDConfiguration {
|
||||
|
||||
}
|
|
@ -1,427 +0,0 @@
|
|||
/*
|
||||
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.net.*;
|
||||
import javax.media.*;
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
import org.thdl.util.ThdlDebug;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public class QDPlayer extends Panel implements ControllerListener
|
||||
{
|
||||
private EventListenerList listenerList = new EventListenerList();
|
||||
|
||||
public URL mediaURL;
|
||||
|
||||
private Vector orderStartID, orderEndID;
|
||||
private Stack pileStart, pileEnd;
|
||||
private Hashtable hashStart, hashEnd;
|
||||
|
||||
private Player player = null;
|
||||
private Component visualComponent = null;
|
||||
private Component controlComponent = null;
|
||||
private Panel panel = null;
|
||||
private JPanel vPanel = null;
|
||||
|
||||
private Container parent = null;
|
||||
|
||||
private java.util.Timer timer = null;
|
||||
private Time stopTime = null;
|
||||
private Time pauseTime = null;
|
||||
private boolean stillLoadingVideo = false;
|
||||
private boolean isMediaAudio = false;
|
||||
private boolean isSized = false;
|
||||
|
||||
private Float to = null;
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public QDPlayer(Container p, URL sound) {
|
||||
parent = p;
|
||||
makeMedia(sound);
|
||||
}
|
||||
public void makeMedia(URL sound) {
|
||||
if (mediaURL != null) {
|
||||
cmd_stop();
|
||||
destroy();
|
||||
}
|
||||
mediaURL = sound;
|
||||
start();
|
||||
}
|
||||
public URL getURL() {
|
||||
return mediaURL;
|
||||
}
|
||||
public void destroy() {
|
||||
player.close();
|
||||
}
|
||||
public void start() {
|
||||
openPlayer();
|
||||
}
|
||||
public Component popVisualComponent()
|
||||
{
|
||||
vPanel.remove(visualComponent);
|
||||
invalidate();
|
||||
validate();
|
||||
repaint();
|
||||
return visualComponent;
|
||||
}
|
||||
public void restoreVisualComponent()
|
||||
{
|
||||
vPanel.add("Center", visualComponent);
|
||||
invalidate();
|
||||
validate();
|
||||
repaint();
|
||||
}
|
||||
public Component getVisualComponent()
|
||||
{
|
||||
return visualComponent;
|
||||
}
|
||||
public Component getControlComponent()
|
||||
{
|
||||
return controlComponent;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public boolean cmd_isSized() {
|
||||
return isSized;
|
||||
}
|
||||
public boolean cmd_isRealized() {
|
||||
return player.getState() == Controller.Realized;
|
||||
}
|
||||
public String cmd_firstS() {
|
||||
return (String)orderStartID.elementAt(0);
|
||||
}
|
||||
public boolean cmd_stop() {
|
||||
if (player == null)
|
||||
return false;
|
||||
try {
|
||||
player.stop();
|
||||
return true;
|
||||
} catch (NotRealizedError err) {
|
||||
System.out.println("NotRealizedError");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean cmd_isID(String theID) {
|
||||
System.out.println(hashStart.containsKey(theID));
|
||||
return hashStart.containsKey(theID);
|
||||
}
|
||||
public boolean cmd_play() {
|
||||
if (stillLoadingVideo || player == null)
|
||||
return false;
|
||||
if (player.getState() == Controller.Started)
|
||||
return true;
|
||||
|
||||
if (pauseTime == null)
|
||||
player.setMediaTime(new Time(0.0));
|
||||
else
|
||||
player.setMediaTime(pauseTime);
|
||||
if (player.getTargetState() < Player.Started) {
|
||||
player.setStopTime(Clock.RESET);
|
||||
player.prefetch();
|
||||
}
|
||||
player.start();
|
||||
return true;
|
||||
}
|
||||
public boolean cmd_playFrom(Integer from) {
|
||||
if (stillLoadingVideo)
|
||||
return false;
|
||||
if (play(from, null))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public boolean cmd_play(Integer from, Integer to) {
|
||||
if (stillLoadingVideo)
|
||||
return false;
|
||||
if (play(from, to))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public int getLastTime() {
|
||||
Time t = player.getDuration();
|
||||
long l = t.getNanoseconds();
|
||||
return new Long(l / 1000000).intValue();
|
||||
}
|
||||
public int when() {
|
||||
if (player == null)
|
||||
return -1;
|
||||
if (player.getState() < Controller.Realized)
|
||||
return -1;
|
||||
long currTime = player.getMediaNanoseconds();
|
||||
return new Long(currTime / 1000000).intValue();
|
||||
}
|
||||
private boolean play(Integer from, Integer to) {
|
||||
if (player == null)
|
||||
return false;
|
||||
|
||||
final Time startTime = new Time(from.longValue() * 1000000);
|
||||
try {
|
||||
if (player.getState() == Controller.Started)
|
||||
player.stop();
|
||||
while (player.getState() == Controller.Unrealized)
|
||||
;
|
||||
|
||||
// player.stop();
|
||||
if (to == null) {
|
||||
stopTime = null;
|
||||
player.setStopTime(Clock.RESET);
|
||||
} else {
|
||||
stopTime = new Time(to.longValue() * 1000000);
|
||||
player.setStopTime(stopTime);
|
||||
}
|
||||
player.setMediaTime(startTime);
|
||||
player.prefetch();
|
||||
player.start();
|
||||
return true;
|
||||
} catch(NotRealizedError err) {
|
||||
System.out.println("NotRealizedError");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
public void openPlayer() {
|
||||
try {
|
||||
player = Manager.createPlayer(mediaURL);
|
||||
player.addControllerListener(this);
|
||||
} catch (javax.media.NoPlayerException e) {
|
||||
System.err.println("noplayer exception");
|
||||
e.printStackTrace();
|
||||
ThdlDebug.noteIffyCode();
|
||||
return;
|
||||
} catch (java.io.IOException ex) {
|
||||
System.err.println("IO exception");
|
||||
ex.printStackTrace();
|
||||
ThdlDebug.noteIffyCode();
|
||||
return;
|
||||
}
|
||||
if (player != null)
|
||||
player.realize();
|
||||
}
|
||||
public synchronized void controllerUpdate(ControllerEvent event) {
|
||||
if (player == null)
|
||||
return;
|
||||
if (event instanceof RealizeCompleteEvent) {
|
||||
System.out.println("received RealizeCompleteEvent event");
|
||||
if (visualComponent == null) {
|
||||
if (panel == null) {
|
||||
setLayout(new GridLayout(1,1));
|
||||
vPanel = new JPanel();
|
||||
vPanel.setLayout( new BorderLayout() );
|
||||
if ((visualComponent = player.getVisualComponent())!= null)
|
||||
vPanel.add("Center", visualComponent);
|
||||
else {
|
||||
isMediaAudio = true;
|
||||
stillLoadingVideo = false;
|
||||
}
|
||||
if (!stillLoadingVideo)
|
||||
{
|
||||
if ((controlComponent = player.getControlPanelComponent()) != null) {
|
||||
if (visualComponent == null) //no video
|
||||
vPanel.setPreferredSize(new Dimension(400,25));
|
||||
vPanel.add("South", controlComponent);
|
||||
}
|
||||
}
|
||||
add(vPanel);
|
||||
}
|
||||
}
|
||||
parent.invalidate();
|
||||
parent.validate();
|
||||
parent.repaint();
|
||||
isSized = true;
|
||||
if (stillLoadingVideo)
|
||||
player.start();
|
||||
} else if (event instanceof StartEvent) {
|
||||
StartEvent se = (StartEvent)event;
|
||||
Time t = se.getMediaTime();
|
||||
long longt = t.getNanoseconds();
|
||||
Float from = new Float(longt);
|
||||
float f = (from.floatValue() / 1000000000);
|
||||
from = new Float(f);
|
||||
t = player.getStopTime();
|
||||
longt = t.getNanoseconds();
|
||||
to = new Float(longt);
|
||||
f = (to.floatValue() / 1000000000);
|
||||
to = new Float(f);
|
||||
if (timer != null)
|
||||
{
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
timer = new java.util.Timer(true);
|
||||
timer.schedule(new TimerTask() {
|
||||
public void run() {
|
||||
//this is specifically for the MPG stop time bug
|
||||
if (stopTime != null)
|
||||
if (player.getMediaTime().getNanoseconds() > stopTime.getNanoseconds())
|
||||
player.stop();
|
||||
}}, 0, 15);
|
||||
} else if (event instanceof StopEvent) {
|
||||
pauseTime = player.getMediaTime();
|
||||
|
||||
|
||||
/*messy problems require messy solutions:
|
||||
if the slider is present, dragging it while playing creates
|
||||
a RestartingEvent, and if I set the media time here it messes up
|
||||
and barely plays at all (maybe because it cancels the previously
|
||||
set media time? - I don't know).
|
||||
|
||||
but it seems that if you press the play/pause button on the
|
||||
control widget, then you need to set the media time upon stop
|
||||
(probably because of problem noted below, namely that you get
|
||||
weird results if you do player.start() without setting the media
|
||||
time.*/
|
||||
|
||||
if (!(event instanceof RestartingEvent))
|
||||
player.setMediaTime(pauseTime);
|
||||
|
||||
// player.setStopTime(Clock.RESET);
|
||||
stopTime = null;
|
||||
|
||||
System.out.println("received StopEvent");
|
||||
|
||||
if (timer != null)
|
||||
{
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
if (stillLoadingVideo)
|
||||
{
|
||||
System.out.println("received EndOfMediaEvent");
|
||||
stillLoadingVideo = false;
|
||||
player.stop();
|
||||
if ((controlComponent = player.getControlPanelComponent()) != null) {
|
||||
if (visualComponent == null) //no video
|
||||
vPanel.setPreferredSize(new Dimension(400,25));
|
||||
vPanel.add("South", controlComponent);
|
||||
}
|
||||
parent.invalidate();
|
||||
parent.validate();
|
||||
parent.repaint();
|
||||
}
|
||||
} else if ( event instanceof CachingControlEvent) {
|
||||
CachingControlEvent e = (CachingControlEvent) event;
|
||||
System.out.println("got CachingControlEvent: " + e);
|
||||
if (!isMediaAudio)
|
||||
stillLoadingVideo = true;
|
||||
} else if (event instanceof ControllerErrorEvent) {
|
||||
player = null;
|
||||
System.err.println("*** ControllerErrorEvent *** " + ((ControllerErrorEvent)event).getMessage());
|
||||
} else if (event instanceof PrefetchCompleteEvent) {
|
||||
if (panel != null) {
|
||||
panel.invalidate();
|
||||
}
|
||||
parent.invalidate();
|
||||
parent.validate();
|
||||
parent.repaint();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
After pause the MPEG video and playing it again it gets faster
|
||||
Author: vladshtr
|
||||
In Reply To: After pause the MPEG video and playing it again it gets faster
|
||||
Mar 1, 2001 6:25 PM
|
||||
|
||||
Reply 1 of 1
|
||||
|
||||
|
||||
The problem is in the setting the Meida time.
|
||||
|
||||
The safety way is to always set new media time with the
|
||||
following method: setMediaTime(Time time); .... if you want to
|
||||
use it after
|
||||
-player.stop(); used as real stop you can use setMediaTime(new
|
||||
Time(0.0));
|
||||
-player.stop(); used as real pause you have to use the
|
||||
combination:
|
||||
player.stop();
|
||||
Time currentTime = player.getMediaTime();
|
||||
//........
|
||||
player.setMediaTime(currentTime);
|
||||
player.start();
|
||||
|
||||
|
||||
Re: (urgent) when you pause and resume, video plays at rate > 1
|
||||
Author: seertenedos
|
||||
In Reply To: (urgent) when you pause and resume, video plays at rate > 1
|
||||
Aug 11, 2002 11:36 PM
|
||||
|
||||
Reply 1 of 1
|
||||
|
||||
|
||||
I found a solution for this problem for those that are interested.
|
||||
|
||||
what you have to do is store the time just before you pause and then set the
|
||||
time just before you play. here is a copy of my pause and play methods
|
||||
|
||||
// Start the player
|
||||
private void play() {
|
||||
if (player != null)
|
||||
{
|
||||
if (pauseTime != null)
|
||||
{
|
||||
player.setMediaTime(pauseTime);
|
||||
}
|
||||
if (player.getTargetState() < Player.Started)
|
||||
player.prefetch();
|
||||
player.start();
|
||||
}
|
||||
}
|
||||
|
||||
// Pause the player
|
||||
private void pause() {
|
||||
if (player != null)
|
||||
pauseTime = player.getMediaTime();
|
||||
player.stop();
|
||||
}
|
||||
|
||||
|
||||
that should solve your pause play problems!
|
||||
|
||||
> The problem is below. It seems quite a few people are
|
||||
> having this problem but i have not seen a solution
|
||||
> around. I really need a solution to this problem as
|
||||
> the whole point of my application is that it plays
|
||||
> divx and mpeg videos. At the moment i have divx
|
||||
> movies playing through the mpeg demuxer as the avi one
|
||||
> stuffed up the audio. I think that is the reason it
|
||||
> affects both divx and mpeg. My application is due in
|
||||
> one week and my client is not going to be very happy
|
||||
> if this problem happens every time they pause then
|
||||
> play the video.
|
||||
> The player is for divx movies. If anyone knows how to
|
||||
> solve this problem or how to make it so you can pause
|
||||
> and resume divx movies please respond.
|
||||
>
|
||||
> Pause and Resume playback.
|
||||
> The video plays at a high rate and there is no audio.
|
||||
> Problem doesn't appear while seeking.
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
|
||||
*/
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
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.io.*;
|
||||
import java.awt.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.text.*;
|
||||
import javax.swing.text.rtf.*;
|
||||
|
||||
import org.thdl.media.*;
|
||||
import org.thdl.util.ThdlDebug;
|
||||
import org.thdl.util.ThdlActionListener;
|
||||
import org.thdl.util.ThdlOptions;
|
||||
import org.thdl.tib.input.JskadKeyboardManager;
|
||||
import org.thdl.tib.input.JskadKeyboardFactory;
|
||||
import org.thdl.tib.input.JskadKeyboard;
|
||||
import org.thdl.util.ThdlI18n;
|
||||
|
||||
import org.thdl.savant.JdkVersionHacks;
|
||||
|
||||
|
||||
public class QDShell extends JFrame {
|
||||
protected static final String defaultConfiguration = new String("http://iris.lib.virginia.edu/tibet/education/tllr/xml/lacito-thdl_qdConfig.xml");
|
||||
|
||||
/** the middleman that keeps code regarding Tibetan keyboards
|
||||
* clean */
|
||||
/*
|
||||
private final static JskadKeyboardManager keybdMgr
|
||||
= new JskadKeyboardManager(JskadKeyboardFactory.getAllAvailableJskadKeyboards());
|
||||
*/
|
||||
/** When opening a file, this is the only extension QuillDriver
|
||||
cares about. This is case-insensitive. */
|
||||
protected final static String dotQuillDriver = ".xml";
|
||||
|
||||
ResourceBundle messages = null;
|
||||
QD qd = null;
|
||||
QDConfiguration qdConfig;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
ThdlDebug.attemptToSetUpLogFile("qd", ".log");
|
||||
|
||||
Locale locale;
|
||||
|
||||
/*
|
||||
if (args.length == 3) {
|
||||
locale = new Locale(new String(args[1]), new String(args[2]));
|
||||
ThdlI18n.setLocale(locale);
|
||||
}
|
||||
*/
|
||||
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
|
||||
QDShell qdsh = new QDShell(args);
|
||||
qdsh.setVisible(true);
|
||||
} catch (NoClassDefFoundError err) {
|
||||
ThdlDebug.handleClasspathError("QuillDriver's CLASSPATH", err);
|
||||
}
|
||||
}
|
||||
|
||||
public QDShell(String[] args) {
|
||||
String configURL = null;
|
||||
String newURL = null;
|
||||
String editURL = null;
|
||||
String dtdURL = null;
|
||||
|
||||
switch (args.length) {
|
||||
case 4: dtdURL = new String(args[3]);
|
||||
case 3: newURL = new String(args[2]);
|
||||
case 2: editURL = new String(args[1]);
|
||||
case 1: configURL = new String(args[0]);
|
||||
}
|
||||
|
||||
setTitle("QuillDriver");
|
||||
messages = ThdlI18n.getResourceBundle();
|
||||
|
||||
// Code for Merlin
|
||||
if (JdkVersionHacks.maximizedBothSupported(getToolkit())) {
|
||||
setLocation(0,0);
|
||||
setSize(getToolkit().getScreenSize().width,getToolkit().getScreenSize().height);
|
||||
setVisible(true);
|
||||
|
||||
// call setExtendedState(Frame.MAXIMIZED_BOTH) if possible:
|
||||
if (!JdkVersionHacks.maximizeJFrameInBothDirections(this)) {
|
||||
throw new Error("badness at maximum: the frame state is supported, but setting that state failed. JdkVersionHacks has a bug.");
|
||||
}
|
||||
} else {
|
||||
Dimension gs = getToolkit().getScreenSize();
|
||||
setLocation(0,0);
|
||||
setSize(new Dimension(gs.width, gs.height));
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
if (args.length == 4) {
|
||||
qd = new QD(configURL, editURL, newURL, dtdURL);
|
||||
getContentPane().add(qd);
|
||||
setJMenuBar(getQDShellMenu());
|
||||
} else {
|
||||
try {
|
||||
String home = System.getProperty("user.home");
|
||||
String sep = System.getProperty("file.separator");
|
||||
String path = "file:" + home + sep + "put-in-home-directory" + sep;
|
||||
qd = new QD(path+"config.xml", path+"edit.xsl", path+"new.xsl", path+"dtd.dtd");
|
||||
getContentPane().add(qd);
|
||||
setJMenuBar(getQDShellMenu());
|
||||
} catch (SecurityException se) {
|
||||
se.printStackTrace();
|
||||
}
|
||||
}
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
addWindowListener(new WindowAdapter () {
|
||||
public void windowClosing (WindowEvent e) {
|
||||
qd.saveTranscript();
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public JMenuBar getQDShellMenu() {
|
||||
JMenu projectMenu = new JMenu(messages.getString("File"));
|
||||
|
||||
JMenuItem newItem = new JMenuItem(messages.getString("New"));
|
||||
newItem.addActionListener(new ThdlActionListener() {
|
||||
public void theRealActionPerformed(ActionEvent e) {
|
||||
qd.saveTranscript();
|
||||
String s = "To start a new annotation, first open a video, " +
|
||||
"and then create and save an empty annotation file.";
|
||||
JFileChooser fc = new JFileChooser();
|
||||
if (fc.showDialog(QDShell.this, messages.getString("SelectMedia")) == JFileChooser.APPROVE_OPTION) {
|
||||
File mediaFile = fc.getSelectedFile();
|
||||
try {
|
||||
JFileChooser fc2 = new JFileChooser();
|
||||
fc2.addChoosableFileFilter(new QDFileFilter());
|
||||
if (fc2.showDialog(QDShell.this, messages.getString("SaveTranscript")) == JFileChooser.APPROVE_OPTION) {
|
||||
File transcriptFile = fc2.getSelectedFile();
|
||||
String mediaString = mediaFile.toURL().toString();
|
||||
qd.newTranscript(transcriptFile, mediaString);
|
||||
}
|
||||
} catch (MalformedURLException murle) {
|
||||
murle.printStackTrace();
|
||||
ThdlDebug.noteIffyCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem openItem = new JMenuItem(messages.getString("Open"));
|
||||
openItem.addActionListener(new ThdlActionListener() {
|
||||
public void theRealActionPerformed(ActionEvent e) {
|
||||
qd.saveTranscript();
|
||||
JFileChooser fc = new JFileChooser();
|
||||
fc.addChoosableFileFilter(new QDFileFilter());
|
||||
if (fc.showDialog(QDShell.this, messages.getString("OpenTranscript")) == JFileChooser.APPROVE_OPTION) {
|
||||
File transcriptFile = fc.getSelectedFile();
|
||||
qd.loadTranscript(transcriptFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem saveItem = new JMenuItem(messages.getString("Save"));
|
||||
saveItem.addActionListener(new ThdlActionListener() {
|
||||
public void theRealActionPerformed(ActionEvent e) {
|
||||
qd.saveTranscript();
|
||||
}
|
||||
});
|
||||
|
||||
JMenuItem quitItem = new JMenuItem(messages.getString("Quit"));
|
||||
quitItem.addActionListener(new ThdlActionListener() {
|
||||
public void theRealActionPerformed(ActionEvent e) {
|
||||
qd.saveTranscript();
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
projectMenu.add(newItem);
|
||||
projectMenu.addSeparator();
|
||||
projectMenu.add(openItem);
|
||||
projectMenu.add(saveItem);
|
||||
projectMenu.addSeparator();
|
||||
projectMenu.add(quitItem);
|
||||
|
||||
//Tibetan-specific value: remove in non-Tibetan version
|
||||
//non-Tibetan specific version would have Transcription Language option here instead
|
||||
|
||||
/*
|
||||
JMenu keyboardMenu = new JMenu(messages.getString("Keyboard"));
|
||||
|
||||
for (int i = 0; i < keybdMgr.size(); i++) {
|
||||
final JskadKeyboard kbd = keybdMgr.elementAt(i);
|
||||
if (kbd.hasQuickRefFile()) {
|
||||
JMenuItem keybdItem = new JMenuItem(kbd.getIdentifyingString());
|
||||
keybdItem.addActionListener(new ThdlActionListener() {
|
||||
public void theRealActionPerformed(ActionEvent e) {
|
||||
qd.changeKeyboard(kbd);
|
||||
}
|
||||
});
|
||||
keyboardMenu.add(keybdItem);
|
||||
}
|
||||
}*/
|
||||
|
||||
JMenu mediaPlayerMenu = new JMenu(messages.getString("MediaPlayer"));
|
||||
java.util.List moviePlayers = SmartPlayerFactory.getAllAvailableSmartPlayers();
|
||||
for (int i=0; i<moviePlayers.size(); i++) {
|
||||
final SmartMoviePanel mPlayer = (SmartMoviePanel)moviePlayers.get(i);
|
||||
JMenuItem mItem = new JMenuItem(mPlayer.getIdentifyingName());
|
||||
mItem.addActionListener(new ThdlActionListener() {
|
||||
public void theRealActionPerformed(ActionEvent e) {
|
||||
qd.setMediaPlayer(mPlayer);
|
||||
}
|
||||
});
|
||||
mediaPlayerMenu.add(mItem);
|
||||
}
|
||||
|
||||
JMenu preferencesMenu = new JMenu(messages.getString("Preferences"));
|
||||
// preferencesMenu.add(keyboardMenu);
|
||||
if (moviePlayers.size() > 0) {
|
||||
SmartMoviePanel defaultPlayer = (SmartMoviePanel)moviePlayers.get(0);
|
||||
qd.setMediaPlayer(defaultPlayer); //set qd media player to default
|
||||
if (moviePlayers.size() > 1)
|
||||
preferencesMenu.add(mediaPlayerMenu);
|
||||
}
|
||||
|
||||
JMenu[] configMenus = qd.getConfiguredMenus();
|
||||
JMenuBar bar = new JMenuBar();
|
||||
bar.add(projectMenu);
|
||||
for (int i=0; i<configMenus.length; i++) bar.add(configMenus[i]);
|
||||
bar.add(preferencesMenu);
|
||||
return bar;
|
||||
}
|
||||
|
||||
private class QDFileFilter extends javax.swing.filechooser.FileFilter {
|
||||
// accepts all directories and all savant files
|
||||
|
||||
public boolean accept(File f) {
|
||||
if (f.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
return f.getName().toLowerCase().endsWith(QDShell.dotQuillDriver);
|
||||
}
|
||||
|
||||
//the description of this filter
|
||||
public String getDescription() {
|
||||
return "QD File Format (" + QDShell.dotQuillDriver + ")";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<xsl:stylesheet
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
||||
xmlns:jskad="xalan://org.thdl.tib.text">
|
||||
|
||||
<xsl:output method="html"/>
|
||||
<xsl:template match="qd">
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
<xsl:value-of select="jskad:TibetanHTML.getStyles(28)" disable-output-escaping="yes"/>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<xsl:apply-templates select="metadata/title" />
|
||||
<xsl:apply-templates select="text" />
|
||||
<xsl:apply-templates select="metadata/workhistory" />
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="title">
|
||||
<xsl:value-of select="." />
|
||||
<p />
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="text">
|
||||
<xsl:apply-templates select="node()" />
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="who">
|
||||
<p />
|
||||
<xsl:variable name="idvar" select="@id" />
|
||||
<xsl:variable name="name" select="../../metadata/speakers/speaker[@iconid=$idvar]" />
|
||||
<u><xsl:value-of select="jskad:TibetanHTML.getHTML($name)" disable-output-escaping="yes"/></u>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="text()">
|
||||
<xsl:value-of select="jskad:TibetanHTML.getIndentedHTML(.)" disable-output-escaping="yes"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="workhistory">
|
||||
<p />
|
||||
<b>Work History</b>
|
||||
<p/>
|
||||
<table width="100%" border="1">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Task</th>
|
||||
<th>Start Time</th>
|
||||
<th>Duration</th>
|
||||
</tr>
|
||||
<xsl:apply-templates select="work"/>
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="work">
|
||||
<tr>
|
||||
<td><xsl:value-of select="name" disable-output-escaping="yes"/></td>
|
||||
<td><xsl:value-of select="task" disable-output-escaping="yes"/></td>
|
||||
<td><xsl:value-of select="start" /></td>
|
||||
<td><xsl:value-of select="duration" /> minutes</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -1,43 +0,0 @@
|
|||
package org.thdl.quilldriver;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class XMLParameters {
|
||||
private HashMap displayYesNo, displayContentsYesNo, displays;
|
||||
|
||||
public XMLParameters() {
|
||||
displayYesNo = new HashMap();
|
||||
displayContentsYesNo = new HashMap();
|
||||
displays = new HashMap();
|
||||
}
|
||||
public boolean containsTag(String tag) {
|
||||
if (displayYesNo.get(tag) == null) return false;
|
||||
else return true;
|
||||
}
|
||||
public void addTagOptions(String tag, Boolean display, Boolean displayContents, String displayAs) {
|
||||
displayYesNo.put(tag, display);
|
||||
displayContentsYesNo.put(tag, displayContents);
|
||||
displays.put(tag, displayAs);
|
||||
}
|
||||
public void removeTagOptions(String tag) {
|
||||
displayYesNo.remove(tag);
|
||||
displayContentsYesNo.remove(tag);
|
||||
displays.remove(tag);
|
||||
}
|
||||
|
||||
public boolean isTagForDisplay(String tag) {
|
||||
Object obj = displayYesNo.get(tag);
|
||||
if (obj == null) return false;
|
||||
else return ((Boolean)obj).booleanValue();
|
||||
}
|
||||
public boolean areTagContentsForDisplay(String tag) {
|
||||
Object obj = displayContentsYesNo.get(tag);
|
||||
if (obj == null) return false;
|
||||
else return ((Boolean)obj).booleanValue();
|
||||
}
|
||||
public getDisplayForTag(String tag) {
|
||||
Object obj = displayAs.get(tag);
|
||||
if (obj == null) return null;
|
||||
else return (String)obj;
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package org.thdl.quilldriver;
|
||||
|
||||
import org.jaxen.XPath;
|
||||
import org.jaxen.JaxenException;
|
||||
import org.jaxen.jdom.JDOMXPath;
|
||||
import java.util.List;
|
||||
|
||||
public class TranscriptNavigator {
|
||||
private TranscriptNavigator() {} //can't instantiate this class
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
public static List findNodeSet(Object jdomNode, String xpathExpression) {
|
||||
if (jdomNode == null)
|
||||
return null;
|
||||
try {
|
||||
XPath path = new JDOMXPath(xpathExpression);
|
||||
return path.selectNodes(jdomNode);
|
||||
} catch (JaxenException je) {
|
||||
je.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,180 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,788 +0,0 @@
|
|||
package org.thdl.quilldriver;
|
||||
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.Attribute;
|
||||
import org.jdom.Text;
|
||||
import org.jdom.DocType;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.MouseMotionAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.EventObject;
|
||||
import java.util.EventListener;
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.text.Keymap;
|
||||
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;
|
||||
import javax.swing.text.DefaultEditorKit;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.CaretListener;
|
||||
import javax.swing.event.CaretEvent;
|
||||
import javax.swing.event.EventListenerList;
|
||||
|
||||
public class XMLEditor {
|
||||
private EventListenerList listenerList = new EventListenerList();
|
||||
private Document xml;
|
||||
private JTextPane pane;
|
||||
private StyledDocument doc;
|
||||
private DocumentListener docListen;
|
||||
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.darkGray;
|
||||
private Cursor textCursor;
|
||||
private Cursor defaultCursor;
|
||||
private boolean isEditing = false;
|
||||
private Object editingNode = null;
|
||||
private boolean hasChanged = false;
|
||||
private Hashtable actions;
|
||||
private CaretListener editabilityTracker;
|
||||
private XMLTagInfo tagInfo;
|
||||
|
||||
public XMLEditor(Document xmlDoc, JTextPane textPane, XMLTagInfo tagInfo) {
|
||||
xml = xmlDoc;
|
||||
pane = textPane;
|
||||
this.tagInfo = tagInfo;
|
||||
startOffsets = new HashMap();
|
||||
endOffsets = new HashMap();
|
||||
|
||||
docListen = new DocumentListener() {
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
hasChanged = true;
|
||||
}
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
hasChanged = true;
|
||||
if (getStartOffsetForNode(editingNode) > e.getOffset()) {
|
||||
javax.swing.text.Document d = e.getDocument();
|
||||
try {
|
||||
startOffsets.put(editingNode, d.createPosition(e.getOffset()));
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
hasChanged = true;
|
||||
}
|
||||
};
|
||||
render();
|
||||
|
||||
textCursor = new Cursor(Cursor.TEXT_CURSOR);
|
||||
defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR);
|
||||
|
||||
pane.addMouseMotionListener(new MouseMotionAdapter() {
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int offset = p.viewToModel(e.getPoint());
|
||||
if (isEditable(offset)) p.setCursor(textCursor);
|
||||
else p.setCursor(defaultCursor);
|
||||
}
|
||||
});
|
||||
|
||||
MouseListener[] listeners = (MouseListener[])pane.getListeners(MouseListener.class);
|
||||
for (int i=0; i<listeners.length; i++) pane.removeMouseListener(listeners[i]);
|
||||
pane.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int offset = p.viewToModel(e.getPoint());
|
||||
if (isEditable(offset)) {
|
||||
p.requestFocus();
|
||||
if (isEditing) fireEndEditEvent();
|
||||
fireStartEditEvent(getNodeForOffset(offset));
|
||||
p.setCaretPosition(offset);
|
||||
} else {
|
||||
Object node = getNodeForOffset(offset);
|
||||
if (isEditing) fireEndEditEvent();
|
||||
if (node != null) fireCantEditEvent(getNodeForOffset(offset));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pane.addFocusListener(new FocusListener() {
|
||||
public void focusGained(FocusEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
if (isEditable(p.getCaretPosition()))
|
||||
fireStartEditEvent(getNodeForOffset(p.getCaretPosition()));
|
||||
}
|
||||
public void focusLost(FocusEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
if (isEditing) fireEndEditEvent();
|
||||
}
|
||||
});
|
||||
|
||||
editabilityTracker = new CaretListener() {
|
||||
public void caretUpdate(CaretEvent e) {
|
||||
int dot = e.getDot();
|
||||
if (getNodeForOffset(dot) != getNodeForOffset(e.getMark()))
|
||||
pane.getCaret().setDot(dot);
|
||||
if (!isEditable(dot)) {
|
||||
while (!isEditable(dot) && dot<pane.getDocument().getLength()) dot++;
|
||||
if (dot == pane.getDocument().getLength()) {
|
||||
dot = e.getDot();
|
||||
do {
|
||||
dot--;
|
||||
} while (!isEditable(dot) && dot>-1);
|
||||
if (dot == -1) return; //what to do? there's nothing to edit in this pane
|
||||
}
|
||||
if (isEditable(dot)) {
|
||||
pane.getCaret().setDot(dot);
|
||||
if (getNodeForOffset(dot) != null) fireStartEditEvent(getNodeForOffset(dot));
|
||||
}
|
||||
} else if (editingNode == null) //need to start editing because cursor happens to be on an editable node
|
||||
fireStartEditEvent(getNodeForOffset(dot));
|
||||
}
|
||||
};
|
||||
|
||||
Action nextNodeAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int prePos = p.getCaretPosition();
|
||||
Object node = getNodeForOffset(prePos);
|
||||
int i = prePos+1;
|
||||
while (i<p.getDocument().getLength() && isEditable(i) && getNodeForOffset(i) == node) i++;
|
||||
while (i<p.getDocument().getLength() && !isEditable(i)) i++;
|
||||
node = getNodeForOffset(i);
|
||||
while (i<p.getDocument().getLength() && isEditable(i) && getNodeForOffset(i) == node) i++;
|
||||
if (isEditing) fireEndEditEvent();
|
||||
i--;
|
||||
fireStartEditEvent(getNodeForOffset(i));
|
||||
p.setCaretPosition(i);
|
||||
}
|
||||
};
|
||||
|
||||
Action selectNodeAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
Object node = getNodeForOffset(p.getCaretPosition());
|
||||
if (node != null) {
|
||||
p.setSelectionStart(((Position)startOffsets.get(node)).getOffset());
|
||||
int end = ((Position)endOffsets.get(node)).getOffset();
|
||||
if (node instanceof Text) p.setSelectionEnd(end);
|
||||
else if (node instanceof Attribute) p.setSelectionEnd(end-1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Action selForwardAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int offset = p.getCaretPosition();
|
||||
Object node = getNodeForOffset(offset);
|
||||
int last = (((Position)endOffsets.get(node)).getOffset());
|
||||
if (node instanceof Attribute) last--;
|
||||
if (offset < last) p.getCaret().moveDot(offset++);
|
||||
}
|
||||
};
|
||||
Action selBackwardAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int offset = p.getCaretPosition();
|
||||
int first = (((Position)startOffsets.get(getNodeForOffset(offset))).getOffset());
|
||||
if (offset > first) p.getCaret().moveDot(offset--);
|
||||
}
|
||||
};
|
||||
|
||||
Action selectToNodeEndAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
Object node = getNodeForOffset(p.getCaret().getMark());
|
||||
if (node != null) {
|
||||
int last = (((Position)endOffsets.get(node)).getOffset());
|
||||
if (node instanceof Attribute) last--;
|
||||
p.getCaret().moveDot(last);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Action selectToNodeStartAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int offset = p.getCaretPosition();
|
||||
Object node = getNodeForOffset(p.getCaret().getMark());
|
||||
if (node != null) {
|
||||
int first = (((Position)startOffsets.get(node)).getOffset());
|
||||
p.getCaret().moveDot(first);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Action backwardAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int prePos = p.getCaretPosition();
|
||||
int newPos = prePos-1;
|
||||
while (newPos>-1 && !isEditable(newPos)) newPos--;
|
||||
if (newPos != -1) {
|
||||
if (getNodeForOffset(prePos) != getNodeForOffset(newPos)) {
|
||||
fireEndEditEvent();
|
||||
fireStartEditEvent(getNodeForOffset(newPos));
|
||||
}
|
||||
p.setCaretPosition(newPos);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Action forwardAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int prePos = p.getCaretPosition();
|
||||
int newPos = prePos+1;
|
||||
while (newPos<p.getDocument().getLength() && !isEditable(newPos)) newPos++;
|
||||
if (newPos != p.getDocument().getLength()) {
|
||||
if (getNodeForOffset(prePos) != getNodeForOffset(newPos)) {
|
||||
fireEndEditEvent();
|
||||
fireStartEditEvent(getNodeForOffset(newPos));
|
||||
}
|
||||
p.setCaretPosition(newPos);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Action begNodeAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
Object node = getNodeForOffset(p.getCaretPosition());
|
||||
p.setCaretPosition(((Position)startOffsets.get(node)).getOffset());
|
||||
}
|
||||
};
|
||||
|
||||
Action endNodeAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
Object node = getNodeForOffset(p.getCaretPosition());
|
||||
p.setCaretPosition(((Position)endOffsets.get(node)).getOffset());
|
||||
}
|
||||
};
|
||||
|
||||
Action deleteNextAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int offset = p.getCaretPosition();
|
||||
int last = (((Position)endOffsets.get(getNodeForOffset(offset))).getOffset());
|
||||
if (offset < last) {
|
||||
StyledDocument d = p.getStyledDocument();
|
||||
try {
|
||||
d.remove(offset, 1);
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Action deletePrevAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int offset = p.getCaretPosition();
|
||||
int first = (((Position)startOffsets.get(getNodeForOffset(offset))).getOffset());
|
||||
if (offset > first) {
|
||||
StyledDocument d = p.getStyledDocument();
|
||||
try {
|
||||
d.remove(offset-1, 1);
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Action loseFocusAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
p.transferFocus(); //moves focus to next component
|
||||
}
|
||||
};
|
||||
|
||||
/* Action selForwardAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JTextPane p = (JTextPane)e.getSource();
|
||||
int offset = p.getCaretPosition();
|
||||
|
||||
}
|
||||
};
|
||||
*/
|
||||
createActionTable(pane);
|
||||
JTextPane tp = new JTextPane();
|
||||
Keymap keymap = tp.addKeymap("KeyBindings", tp.getKeymap());
|
||||
|
||||
KeyStroke[] selectAllKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.selectAllAction));
|
||||
if (selectAllKeys != null)
|
||||
for (int i=0; i<selectAllKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(selectAllKeys[i], selectNodeAction);
|
||||
KeyStroke[] selLineKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.selectLineAction));
|
||||
if (selLineKeys != null)
|
||||
for (int i=0; i<selLineKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(selLineKeys[i], selectNodeAction);
|
||||
KeyStroke[] selParaKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.selectParagraphAction));
|
||||
if (selParaKeys != null)
|
||||
for (int i=0; i<selParaKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(selParaKeys[i], selectNodeAction);
|
||||
KeyStroke[] selEndLineKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.selectionEndLineAction));
|
||||
if (selEndLineKeys != null)
|
||||
for (int i=0; i<selEndLineKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(selEndLineKeys[i], selectToNodeEndAction);
|
||||
KeyStroke[] selEndParaKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.selectionEndParagraphAction));
|
||||
if (selEndParaKeys != null)
|
||||
for (int i=0; i<selEndParaKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(selEndParaKeys[i], selectToNodeEndAction);
|
||||
KeyStroke[] selBegLineKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.selectionBeginLineAction));
|
||||
if (selBegLineKeys != null)
|
||||
for (int i=0; i<selBegLineKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(selBegLineKeys[i], selectToNodeStartAction);
|
||||
KeyStroke[] selBegParaKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.selectionBeginParagraphAction));
|
||||
if (selBegParaKeys != null)
|
||||
for (int i=0; i<selBegParaKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(selBegParaKeys[i], selectToNodeStartAction);
|
||||
KeyStroke[] tabKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.insertTabAction));
|
||||
if (tabKeys != null)
|
||||
for (int i=0; i<tabKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(tabKeys[i], nextNodeAction);
|
||||
KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
|
||||
if (enterKey != null) keymap.addActionForKeyStroke(enterKey, nextNodeAction);
|
||||
KeyStroke[] endLineKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.endLineAction));
|
||||
if (endLineKeys != null)
|
||||
for (int i=0; i<endLineKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(endLineKeys[i], endNodeAction);
|
||||
KeyStroke[] endParaKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.endParagraphAction));
|
||||
if (endParaKeys != null)
|
||||
for (int i=0; i<endParaKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(endParaKeys[i], endNodeAction);
|
||||
KeyStroke[] begLineKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.beginLineAction));
|
||||
if (begLineKeys != null)
|
||||
for (int i=0; i<begLineKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(begLineKeys[i], begNodeAction);
|
||||
KeyStroke[] begParaKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.beginParagraphAction));
|
||||
if (begParaKeys != null)
|
||||
for (int i=0; i<begParaKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(begParaKeys[i], begNodeAction);
|
||||
KeyStroke[] backwardKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.backwardAction));
|
||||
if (backwardKeys != null)
|
||||
for (int i=0; i<backwardKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(backwardKeys[i], backwardAction);
|
||||
KeyStroke[] forwardKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.forwardAction));
|
||||
if (forwardKeys != null)
|
||||
for (int i=0; i<forwardKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(forwardKeys[i], forwardAction);
|
||||
KeyStroke[] delNextKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.deleteNextCharAction));
|
||||
if (delNextKeys != null)
|
||||
for (int i=0; i<delNextKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(delNextKeys[i], deleteNextAction);
|
||||
KeyStroke[] delPrevKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.deletePrevCharAction));
|
||||
if (delPrevKeys != null)
|
||||
for (int i=0; i<delPrevKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(delPrevKeys[i], deletePrevAction);
|
||||
KeyStroke[] selForwardKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.selectionForwardAction));
|
||||
if (selForwardKeys != null)
|
||||
for (int i=0; i<selForwardKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(selForwardKeys[i], selForwardAction);
|
||||
KeyStroke[] selBackKeys = keymap.getKeyStrokesForAction(getActionByName(DefaultEditorKit.selectionBackwardAction));
|
||||
if (selBackKeys != null)
|
||||
for (int i=0; i<selBackKeys.length; i++)
|
||||
keymap.addActionForKeyStroke(selBackKeys[i], selBackwardAction);
|
||||
KeyStroke escapeKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
|
||||
if (escapeKey != null) keymap.addActionForKeyStroke(escapeKey, loseFocusAction);
|
||||
|
||||
/*
|
||||
Actions that still need to be defined:
|
||||
|
||||
Fields inherited from class javax.swing.text.DefaultEditorKit
|
||||
beepAction, beginAction, beginWordAction, copyAction, cutAction,
|
||||
defaultKeyTypedAction,
|
||||
downAction, endAction, EndOfLineStringProperty,
|
||||
endWordAction, insertBreakAction, insertContentAction,
|
||||
nextWordAction, pageDownAction, pageUpAction,
|
||||
pasteAction, previousWordAction, readOnlyAction
|
||||
selectionBeginAction, selectionBeginWordAction,
|
||||
selectionDownAction, selectionEndAction, selectionEndWordAction,
|
||||
selectionNextWordAction, selectionPreviousWordAction,
|
||||
selectionUpAction, selectWordAction,
|
||||
upAction, writableAction
|
||||
*/
|
||||
|
||||
pane.setKeymap(keymap);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
public void setEditabilityTracker(boolean bool) {
|
||||
if (bool) {
|
||||
int p = pane.getCaretPosition();
|
||||
int q;
|
||||
if (pane.getDocument().getLength() == 0)
|
||||
q=0;
|
||||
else {
|
||||
if (p>0) q=p-1;
|
||||
else q=p+1;
|
||||
}
|
||||
pane.setCaretPosition(q);
|
||||
pane.addCaretListener(editabilityTracker); //shouldn't do if already installed
|
||||
pane.setCaretPosition(p);
|
||||
}
|
||||
else pane.removeCaretListener(editabilityTracker);
|
||||
}
|
||||
public void updateNode(Object node) {
|
||||
System.out.println("updating: " + node.toString());
|
||||
if (node == null)
|
||||
return;
|
||||
try {
|
||||
if (node instanceof Text) {
|
||||
int p1 = ((Position)startOffsets.get(node)).getOffset();
|
||||
int p2 = ((Position)endOffsets.get(node)).getOffset();
|
||||
String val = pane.getDocument().getText(p1, p2-p1).trim();
|
||||
Text text = (Text)node;
|
||||
text.setText(val);
|
||||
} else if (node instanceof Attribute) {
|
||||
int p1 = ((Position)startOffsets.get(node)).getOffset();
|
||||
int p2 = ((Position)endOffsets.get(node)).getOffset()-1; //remove right quote
|
||||
String val = pane.getDocument().getText(p1, p2-p1).trim();
|
||||
Attribute att = (Attribute)node;
|
||||
att.setValue(val);
|
||||
}
|
||||
System.out.println("updated: " + node.toString());
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
interface NodeEditListener extends EventListener {
|
||||
public void nodeEditPerformed(NodeEditEvent ned);
|
||||
}
|
||||
public void addNodeEditListener(NodeEditListener ned) {
|
||||
listenerList.add(NodeEditListener.class, ned);
|
||||
}
|
||||
public void removeNodeEditListener(NodeEditListener ned) {
|
||||
listenerList.remove(NodeEditListener.class, ned);
|
||||
}
|
||||
class NodeEditEvent extends EventObject {
|
||||
Object node;
|
||||
|
||||
NodeEditEvent(Object node) {
|
||||
super(node);
|
||||
this.node = node;
|
||||
}
|
||||
public Object getNode() {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
class StartEditEvent extends NodeEditEvent {
|
||||
StartEditEvent(Object node) {
|
||||
super(node);
|
||||
}
|
||||
}
|
||||
class EndEditEvent extends NodeEditEvent {
|
||||
public EndEditEvent(Object node) {
|
||||
super(node);
|
||||
}
|
||||
public boolean hasBeenEdited() {
|
||||
return hasChanged;
|
||||
}
|
||||
}
|
||||
class CantEditEvent extends NodeEditEvent {
|
||||
public CantEditEvent(Object node) {
|
||||
super(node);
|
||||
}
|
||||
}
|
||||
public void fireStartEditEvent(Object node) {
|
||||
//see javadocs on EventListenerList for how following array is structured
|
||||
Object[] listeners = listenerList.getListenerList();
|
||||
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||
if (listeners[i]==NodeEditListener.class)
|
||||
((NodeEditListener)listeners[i+1]).nodeEditPerformed(new StartEditEvent(node));
|
||||
}
|
||||
isEditing = true;
|
||||
editingNode = node;
|
||||
hasChanged = false;
|
||||
}
|
||||
public void fireEndEditEvent() {
|
||||
if (!isEditing) return;
|
||||
//see javadocs on EventListenerList for how following array is structured
|
||||
Object[] listeners = listenerList.getListenerList();
|
||||
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||
if (listeners[i]==NodeEditListener.class)
|
||||
((NodeEditListener)listeners[i+1]).nodeEditPerformed(new EndEditEvent(editingNode));
|
||||
}
|
||||
if (hasChanged) updateNode(editingNode);
|
||||
isEditing = false;
|
||||
editingNode = null;
|
||||
hasChanged = false;
|
||||
}
|
||||
public void fireCantEditEvent(Object node) {
|
||||
//see javadocs on EventListenerList for how following array is structured
|
||||
Object[] listeners = listenerList.getListenerList();
|
||||
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||
if (listeners[i]==NodeEditListener.class)
|
||||
((NodeEditListener)listeners[i+1]).nodeEditPerformed(new CantEditEvent(node));
|
||||
}
|
||||
}
|
||||
|
||||
public void setXMLDocument(Document d, String doctype_elementName, String doctype_systemID) {
|
||||
xml = d;
|
||||
xml.setDocType(new DocType(doctype_elementName, doctype_systemID));
|
||||
render();
|
||||
}
|
||||
public void render() {
|
||||
System.out.println("Rendering the document");
|
||||
doc = pane.getStyledDocument();
|
||||
int len = doc.getLength();
|
||||
try {
|
||||
if (len > 0) doc.remove(0, len);
|
||||
doc.insertString(0, "\n", null);
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
startOffsets.clear();
|
||||
endOffsets.clear();
|
||||
Element root = xml.getRootElement();
|
||||
renderElement(root, 0.0F, doc.getLength());
|
||||
|
||||
SimpleAttributeSet eColor = new SimpleAttributeSet();
|
||||
eColor.addAttribute("xmlnode", root);
|
||||
doc.setParagraphAttributes(doc.getLength(), 1, eColor, false);
|
||||
|
||||
fixOffsets();
|
||||
|
||||
doc.addDocumentListener(docListen);
|
||||
pane.setCaretPosition(0);
|
||||
setEditabilityTracker(true);
|
||||
}
|
||||
|
||||
public void fixOffsets() {
|
||||
//replace Integer values in startOffsets and endOffsets with Positions
|
||||
Set startKeys = startOffsets.keySet();
|
||||
Iterator iter = startKeys.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Object key = iter.next();
|
||||
Object obj = startOffsets.get(key);
|
||||
//if (obj instanceof Position)
|
||||
// startOffsets.put(key, obj); //actually we don't have to do anything here, do we
|
||||
//since the startoffsets are already set!!
|
||||
//else
|
||||
if (obj instanceof Integer) try {
|
||||
Integer val = (Integer)obj;
|
||||
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();
|
||||
Object obj = endOffsets.get(key);
|
||||
//if (obj instanceof Position)
|
||||
// endOffsets.put(key, obj); //actually we don't have to do anything here, do we
|
||||
//since the endoffsets are already set!!
|
||||
//else
|
||||
if (obj instanceof Integer) try {
|
||||
Integer val = (Integer)obj;
|
||||
endOffsets.put(key, doc.createPosition(val.intValue()));
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public int renderElement(Element e, float indent, int insertOffset) {
|
||||
try {
|
||||
Position pos = doc.createPosition(insertOffset);
|
||||
SimpleAttributeSet eAttributes = new SimpleAttributeSet();
|
||||
StyleConstants.setLeftIndent(eAttributes, indent);
|
||||
SimpleAttributeSet eColor = new SimpleAttributeSet();
|
||||
//StyleConstants.setLeftIndent(eColor, indent);
|
||||
StyleConstants.setForeground(eColor, tagColor);
|
||||
eColor.addAttribute("xmlnode", e);
|
||||
if (pos.getOffset()>0) {
|
||||
String s = doc.getText(pos.getOffset()-1, 1);
|
||||
if (s.charAt(0)!='\n') {
|
||||
AttributeSet attSet = doc.getCharacterElement(pos.getOffset()-1).getAttributes();
|
||||
doc.insertString(pos.getOffset(), "\n", attSet);
|
||||
}
|
||||
}
|
||||
int start = pos.getOffset();
|
||||
startOffsets.put(e, new Integer(start));
|
||||
String tagDisplay;
|
||||
if (tagInfo == null) tagDisplay = e.getQualifiedName();
|
||||
else tagDisplay = tagInfo.getTagDisplay(e);
|
||||
doc.insertString(pos.getOffset(), tagDisplay, eColor); //insert element begin tag
|
||||
if (tagInfo == null || tagInfo.areTagContentsForDisplay(e.getQualifiedName())) {
|
||||
List attributes = e.getAttributes();
|
||||
Iterator iter = attributes.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Attribute att = (Attribute)iter.next();
|
||||
if (tagInfo == null || tagInfo.isAttributeForDisplay(att.getQualifiedName(), e.getQualifiedName()))
|
||||
renderAttribute(att, pos.getOffset());
|
||||
}
|
||||
doc.insertString(pos.getOffset(), ":", eColor);
|
||||
doc.setParagraphAttributes(start, pos.getOffset()-start, eAttributes, false);
|
||||
//doc.insertString(pos.getOffset(), "\n", null);
|
||||
List list = e.getContent();
|
||||
iter = list.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Object next = iter.next();
|
||||
if (next instanceof Element) {
|
||||
Element ne = (Element)next;
|
||||
if (tagInfo == null || tagInfo.isTagForDisplay(ne.getQualifiedName()))
|
||||
renderElement(ne, indent + indentIncrement, pos.getOffset());
|
||||
} else if (next instanceof Text) {
|
||||
Text t = (Text)next;
|
||||
if (t.getParent().getContent().size() == 1 || t.getTextTrim().length() > 0)
|
||||
renderText(t, indent + indentIncrement, pos.getOffset());
|
||||
}
|
||||
// Also: Comment ProcessingInstruction CDATA EntityRef
|
||||
}
|
||||
}
|
||||
//start = pos.getOffset();
|
||||
//doc.insertString(start, "}", eColor); //insert element end tag
|
||||
//doc.setParagraphAttributes(start, pos.getOffset(), eAttributes, false);
|
||||
|
||||
if (pos.getOffset()>0) {
|
||||
//String s = doc.getText(pos.getOffset()-1, 1);
|
||||
if (doc.getText(pos.getOffset()-1,1).charAt(0)=='\n')
|
||||
endOffsets.put(e, new Integer(pos.getOffset()-1));
|
||||
else
|
||||
endOffsets.put(e, new Integer(pos.getOffset()));
|
||||
}
|
||||
//endOffsets.put(e, new Integer(pos.getOffset()));
|
||||
return pos.getOffset();
|
||||
//doc.insertString(pos.getOffset(), "\n", null);
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int renderAttribute(Attribute att, int insertOffset) {
|
||||
try {
|
||||
Position pos = doc.createPosition(insertOffset);
|
||||
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();
|
||||
if (pos.getOffset()>0) {
|
||||
String s = doc.getText(pos.getOffset()-1, 1);
|
||||
if (s.charAt(0)!='\n') {
|
||||
AttributeSet attSet = doc.getCharacterElement(pos.getOffset()-1).getAttributes();
|
||||
doc.insertString(pos.getOffset(), " ", attSet);
|
||||
}
|
||||
}
|
||||
String displayName;
|
||||
if (tagInfo == null) displayName = att.getQualifiedName();
|
||||
else displayName = tagInfo.getAttributeDisplay(att.getQualifiedName(), att.getParent().getQualifiedName());
|
||||
doc.insertString(pos.getOffset(), displayName+"=", aColor);
|
||||
startOffsets.put(att, new Integer(pos.getOffset()+1)); //add one so that begin quote is not part of attribute value
|
||||
doc.insertString(pos.getOffset(), "\"" + att.getValue()+"\"", tColor);
|
||||
endOffsets.put(att, new Integer(pos.getOffset()));
|
||||
return pos.getOffset();
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int renderText(Text t, float indent, int insertOffset) {
|
||||
try {
|
||||
Position pos = doc.createPosition(insertOffset);
|
||||
SimpleAttributeSet tAttributes = new SimpleAttributeSet();
|
||||
//StyleConstants.setLeftIndent(tAttributes, indent);
|
||||
StyleConstants.setForeground(tAttributes, textColor);
|
||||
tAttributes.addAttribute("xmlnode", t);
|
||||
doc.insertString(pos.getOffset(), " ", tAttributes); //insert space with text attributes so first character has correct color, xmlnode attribute, etc.
|
||||
String s = t.getTextTrim();
|
||||
int start = pos.getOffset();
|
||||
startOffsets.put(t, new Integer(start));
|
||||
doc.insertString(pos.getOffset(), s, tAttributes); //insert text
|
||||
int end = pos.getOffset();
|
||||
endOffsets.put(t, new Integer(end));
|
||||
doc.insertString(pos.getOffset(), "\n", tAttributes);
|
||||
return pos.getOffset();
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void removeNode(Object node) {
|
||||
if (startOffsets.containsKey(node)) { //note: should recursively eliminate all sub-nodes too!!
|
||||
startOffsets.remove(node);
|
||||
endOffsets.remove(node);
|
||||
}
|
||||
}
|
||||
|
||||
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(int offset) {
|
||||
Object node = getNodeForOffset(offset);
|
||||
if ((node instanceof Text) &&
|
||||
(offset<getStartOffsetForNode(node) || offset>getEndOffsetForNode(node)))
|
||||
return false;
|
||||
else if (node instanceof Attribute &&
|
||||
(offset<getStartOffsetForNode(node) || offset>getEndOffsetForNode(node)-1))
|
||||
return false;
|
||||
else
|
||||
return isEditable(node);
|
||||
}
|
||||
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;
|
||||
}
|
||||
public JTextPane getTextPane() {
|
||||
return pane;
|
||||
}
|
||||
public Document getXMLDocument() {
|
||||
return xml;
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
package org.thdl.quilldriver;
|
||||
|
||||
import java.util.HashMap;
|
||||
import org.jdom.Element;
|
||||
import org.thdl.quilldriver.XMLUtilities;
|
||||
|
||||
public class XMLTagInfo {
|
||||
private HashMap displayYesNo, displayContentsYesNo, displayAs;
|
||||
private HashMap attributeDisplayYesNo, attributeDisplayAs;
|
||||
|
||||
public XMLTagInfo() {
|
||||
displayYesNo = new HashMap();
|
||||
displayContentsYesNo = new HashMap();
|
||||
displayAs = new HashMap();
|
||||
attributeDisplayYesNo = new HashMap();
|
||||
attributeDisplayAs = new HashMap();
|
||||
}
|
||||
public boolean containsTag(String tag) {
|
||||
if (displayYesNo.get(tag) == null) return false;
|
||||
else return true;
|
||||
}
|
||||
public void addTag(String tag, Boolean display, Boolean displayContents, String displayAs) {
|
||||
displayYesNo.put(tag, display);
|
||||
displayContentsYesNo.put(tag, displayContents);
|
||||
this.displayAs.put(tag, displayAs);
|
||||
}
|
||||
public void removeTag(String tag) {
|
||||
displayYesNo.remove(tag);
|
||||
displayContentsYesNo.remove(tag);
|
||||
displayAs.remove(tag);
|
||||
}
|
||||
public void addAttribute(String name, String parentTag, Boolean display, String displayAs) {
|
||||
String s = parentTag + "/@" + name;
|
||||
attributeDisplayYesNo.put(s, display);
|
||||
attributeDisplayAs.put(s, displayAs);
|
||||
}
|
||||
public void removeAttribute(String name, String parentTag) {
|
||||
String s = parentTag + "/@" + name;
|
||||
attributeDisplayYesNo.remove(s);
|
||||
attributeDisplayAs.remove(s);
|
||||
}
|
||||
public boolean isTagForDisplay(String tag) {
|
||||
Object obj = displayYesNo.get(tag);
|
||||
if (obj == null) return true;
|
||||
else return ((Boolean)obj).booleanValue();
|
||||
}
|
||||
public boolean areTagContentsForDisplay(String tag) {
|
||||
Object obj = displayContentsYesNo.get(tag);
|
||||
if (obj == null) return true;
|
||||
else return ((Boolean)obj).booleanValue();
|
||||
}
|
||||
public String getTagDisplay(Element tag) {
|
||||
String name = tag.getQualifiedName();
|
||||
Object obj = displayAs.get(name);
|
||||
if (obj == null) return name;
|
||||
String val = (String)obj;
|
||||
if (val.startsWith("XPATH:")) {
|
||||
Object node = XMLUtilities.findSingleNode(tag, val.substring(val.indexOf(':')+1));
|
||||
if (node == null) return name;
|
||||
String s = XMLUtilities.getTextForNode(node);
|
||||
if (s == null) return name;
|
||||
else return s;
|
||||
} else return val;
|
||||
}
|
||||
public boolean isAttributeForDisplay(String name, String parentTag) {
|
||||
String s = parentTag + "/@" + name;
|
||||
Object obj = attributeDisplayYesNo.get(s);
|
||||
if (obj == null) return true;
|
||||
else return ((Boolean)obj).booleanValue();
|
||||
}
|
||||
public String getAttributeDisplay(String name, String parentTag) {
|
||||
String s = parentTag + "/@" + name;
|
||||
Object obj = attributeDisplayAs.get(s);
|
||||
if (obj == null) return name;
|
||||
else return (String)obj;
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package org.thdl.quilldriver;
|
||||
|
||||
import org.jdom.Text;
|
||||
import org.jdom.Attribute;
|
||||
import org.jdom.Element;
|
||||
import org.jaxen.XPath;
|
||||
import org.jaxen.JaxenException;
|
||||
import org.jaxen.jdom.JDOMXPath;
|
||||
import java.util.List;
|
||||
|
||||
public class XMLUtilities {
|
||||
private XMLUtilities() {}
|
||||
|
||||
public static Object findSingleNode(Object jdomNode, String xpathExpression) {
|
||||
if (jdomNode == null)
|
||||
return null;
|
||||
try {
|
||||
JDOMXPath path = new JDOMXPath(xpathExpression);
|
||||
return path.selectSingleNode(jdomNode);
|
||||
} catch (JaxenException je) {
|
||||
je.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static List findNodeSet(Object jdomNode, String xpathExpression) {
|
||||
if (jdomNode == null)
|
||||
return null;
|
||||
try {
|
||||
JDOMXPath path = new JDOMXPath(xpathExpression);
|
||||
return path.selectNodes(jdomNode);
|
||||
} catch (JaxenException je) {
|
||||
je.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static String getTextForNode(Object jdomNode) {
|
||||
if (jdomNode instanceof Text) {
|
||||
Text t = (Text)jdomNode;
|
||||
return t.getText();
|
||||
} else if (jdomNode instanceof Attribute) {
|
||||
Attribute a = (Attribute)jdomNode;
|
||||
return a.getValue();
|
||||
} else if (jdomNode instanceof Element) {
|
||||
Element e = (Element)jdomNode;
|
||||
return e.getTextTrim();
|
||||
} else return null;
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
package org.thdl.quilldriver;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.Collection;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import org.jdom.Document;
|
||||
import org.thdl.savant.TranscriptView;
|
||||
import org.thdl.quilldriver.XMLEditor;
|
||||
import org.thdl.quilldriver.XMLUtilities;
|
||||
|
||||
|
||||
public class XMLView implements TranscriptView {
|
||||
private XMLEditor editor;
|
||||
private Map startTimeMap;
|
||||
private Map endTimeMap;
|
||||
private Map startOffsetMap;
|
||||
private Map endOffsetMap;
|
||||
private Object jdomContextNode;
|
||||
private String getNodesXPath;
|
||||
private String getStartXPath;
|
||||
private String getEndXPath;
|
||||
|
||||
public XMLView(XMLEditor editor, Object jdomContextNode, String getNodesXPath, String getStartXPath, String getEndXPath) {
|
||||
this.editor = editor;
|
||||
this.jdomContextNode = jdomContextNode;
|
||||
this.getNodesXPath = getNodesXPath;
|
||||
this.getStartXPath = getStartXPath;
|
||||
this.getEndXPath = getEndXPath;
|
||||
startTimeMap = new HashMap();
|
||||
endTimeMap = new HashMap();
|
||||
startOffsetMap = new HashMap();
|
||||
endOffsetMap = new HashMap();
|
||||
refresh();
|
||||
}
|
||||
public void refresh(Object newContextNode) {
|
||||
this.jdomContextNode = newContextNode;
|
||||
refresh();
|
||||
}
|
||||
public void refresh() {
|
||||
startTimeMap.clear();
|
||||
endTimeMap.clear();
|
||||
startOffsetMap.clear();
|
||||
endOffsetMap.clear();
|
||||
List audioNodes = XMLUtilities.findNodeSet(jdomContextNode, getNodesXPath);
|
||||
Iterator iter = audioNodes.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Object node = iter.next();
|
||||
String id = String.valueOf(node.hashCode());
|
||||
Object start = XMLUtilities.findSingleNode(node, getStartXPath);
|
||||
String startVal = XMLUtilities.getTextForNode(start);
|
||||
Object end = XMLUtilities.findSingleNode(node, getEndXPath);
|
||||
String endVal = XMLUtilities.getTextForNode(end);
|
||||
int startOffset = editor.getStartOffsetForNode(node);
|
||||
int endOffset = editor.getEndOffsetForNode(node);
|
||||
if (!(startVal == null || endVal == null || startOffset == -1 || endOffset == -1)) {
|
||||
startTimeMap.put(id, startVal);
|
||||
endTimeMap.put(id, endVal);
|
||||
startOffsetMap.put(id, String.valueOf(startOffset));
|
||||
endOffsetMap.put(id, String.valueOf(endOffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
public String getTitle() {
|
||||
return "No Title";
|
||||
}
|
||||
public JTextComponent getTextComponent() {
|
||||
return (JTextComponent)editor.getTextPane();
|
||||
}
|
||||
public String getIDs() {
|
||||
Set idSet = startTimeMap.keySet();
|
||||
Iterator iter = idSet.iterator();
|
||||
StringBuffer idBuff = new StringBuffer();
|
||||
while (iter.hasNext()) {
|
||||
idBuff.append((String)iter.next());
|
||||
idBuff.append(',');
|
||||
}
|
||||
return idBuff.toString();
|
||||
}
|
||||
public String getT1s() {
|
||||
Collection c = startTimeMap.values();
|
||||
Iterator iter = c.iterator();
|
||||
StringBuffer buff = new StringBuffer();
|
||||
while (iter.hasNext()) {
|
||||
buff.append((String)iter.next());
|
||||
buff.append(',');
|
||||
}
|
||||
return buff.toString();
|
||||
}
|
||||
public String getT2s() {
|
||||
Collection c = endTimeMap.values();
|
||||
Iterator iter = c.iterator();
|
||||
StringBuffer buff = new StringBuffer();
|
||||
while (iter.hasNext()) {
|
||||
buff.append((String)iter.next());
|
||||
buff.append(',');
|
||||
}
|
||||
return buff.toString();
|
||||
}
|
||||
public String getStartOffsets() {
|
||||
Collection c = startOffsetMap.values();
|
||||
Iterator iter = c.iterator();
|
||||
StringBuffer buff = new StringBuffer();
|
||||
while (iter.hasNext()) {
|
||||
buff.append((String)iter.next());
|
||||
buff.append(',');
|
||||
}
|
||||
return buff.toString();
|
||||
}
|
||||
public String getEndOffsets() {
|
||||
Collection c = endOffsetMap.values();
|
||||
Iterator iter = c.iterator();
|
||||
StringBuffer buff = new StringBuffer();
|
||||
while (iter.hasNext()) {
|
||||
buff.append((String)iter.next());
|
||||
buff.append(',');
|
||||
}
|
||||
return buff.toString();
|
||||
}
|
||||
public Document getDocument() {
|
||||
return editor.getXMLDocument();
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
|
||||
@(#)package.html
|
||||
|
||||
Copyright 2001-2002 Tibetan and Himalayan Digital Library
|
||||
|
||||
This software is the confidential and proprietary information of
|
||||
the Tibetan and Himalayan Digital Library. You shall use such
|
||||
information only in accordance with the terms of the license
|
||||
agreement you entered into with the THDL.
|
||||
|
||||
-->
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
Provides facilitates for authoring content to be used by Savant.
|
||||
<p>
|
||||
In the future, this may be combined with Savant, in which case this
|
||||
will be the edit mode. For now, QuillDriver is a stand-alone
|
||||
application.
|
||||
<p>
|
||||
<h2>Related Documentation</h2>
|
||||
@see <a href="../savant/package-summary.html">org.thdl.savant</a>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue