diff --git a/source/MessageBundle.properties b/source/MessageBundle.properties new file mode 100644 index 0000000..d98b861 --- /dev/null +++ b/source/MessageBundle.properties @@ -0,0 +1,75 @@ +Project = Project +ProjectDetails = Project Details +Speakers = Speakers +TimeCoding = Time Coding +AdjustTimeCode = Adjust Time Code +In = Start +Out = Stop +PlaySegment = Play Segment +NewProject = New Project +TitleColon = Title: +TypeNewTitleColon = Type new title: +NoMedia = No media +MediaColon = Media: +NoTranscript = No transcript +TranscriptColon = Transcript: +KeyboardInputMethod = Keyboard Input Method +TranscriberName = Transcriber Name +TranscriberTask = Transcriber Task +Add = Add +FaceColon = Face: +NameColon = Name: +EnterNewSpeakerInfo = Enter new speaker info +Edit = Edit +EditSpeakerInfo = Edit speaker info +Remove = Remove +SureDeleteSpeaker = Are you sure you want to delete this speaker? +Warning = Warning! +Face = Face +Name = Name +SaveCurrent = Save the current transcript +OpenExisting = Open an existing transcript +WhatToDo = What do you want to do? +ChooseOne = Choose an option +Play = Play +Pause = Pause +Mode = Mode +Edit = Edit +ReadOnly = Read-only +View = View +Previous = Previous +Current = Current +Next = Next +SuppressTimes = Hide times +Search = Search +FindText = Find text +ReplaceText = Replace text +FindSpeaker = Find speaker +FindTime = Find time +Cut = Cut +Copy = Copy +Paste = Paste +SelectAll = Select all +InsertSpeaker = Insert speaker +InsertOneTime = Insert a time +InsertTwoTimes = Insert two times +New = New +Open = Open +Close = Close +Save = Save +SaveAs = Save as +Quit = Quit +Keyboard = Keyboard +Preferences = Preferences +FindHeading = Search +FindReplaceHeading = Search and Replace +FindWhat = Find what +ReplaceWith = Replace with +ReplaceQ = Replace? +FindNextYesNo = Find next? +StartFromBeginning = You've reached the end of the document. Do you want to continue searching from the beginning? +TextFound = Text found. +Replace = Replace +ReplaceAll = Replace all +NoReplace = Don't replace +Cancel = Cancel \ No newline at end of file diff --git a/source/MessageBundle_de_DE.properties b/source/MessageBundle_de_DE.properties new file mode 100644 index 0000000..125956b --- /dev/null +++ b/source/MessageBundle_de_DE.properties @@ -0,0 +1,75 @@ +Project = Project Details +ProjectDetails = Projekt +Speakers = Sprecher +TimeCoding = Zeitcode +AdjustTimeCode = Zeitcode regulieren +In = Start +Out = Stop +PlaySegment = Abschnitt abspielen +NewProject = Neues Projekt +TitleColon = Titel: +TypeNewTitleColon = Neue Titeleingabe +NoMedia = Keine Audio/Video-Medien +MediaColon = Audio/Video-Medien: +NoTranscript = Keine Transkription +TranscriptColon = Text-Transkription: +KeyboardInputMethod = Tastatur Eingabemethode +TranscriberName = Transkribierer-Name: +TranscriberTask = Transkribierer-Aufgabe: +Add = Hinzuf黦en +FaceColon = Gesicht +NameColon = Name: +EnterNewSpeakerInfo = Eingabe neue Sprecher-Information +Edit = Bearbeiten +EditSpeakerInfo = Bearbeiten der Srecher-Information +Remove = Entfernen +SureDeleteSpeaker = Wollen Sie wirklich diesen Sprecher l鰏chen? +Warning = Warnung! +Face = Gesicht +Name = Name +SaveCurrent = Gegenw鋜tige Transkription speichern +OpenExisting = Bereits bearbeitete Transkription 鰂fnen +WhatToDo = Was m鯿hten Sie tun? +ChooseOne = W鋒len Sie eine M鰃lichkeit +Play = Abspielen +Pause = Pause +Mode = Moduswahl +Edit = Bearbeiten der Transkription +ReadOnly = Sichten der Transkription +View = Sichten +Previous = Vorhergehender Satz +Current = Gegenw鋜tiger Satz +Next = N鋍hster Satz +SuppressTimes = Entfernen der Zeitzeichen +Search = Search +FindText = Text finden +ReplaceText = Text ersetzen +FindSpeaker = Sprecher finden +FindTime = Zeitabschnitt finden +Cut = Schneiden +Copy = Kopieren +Paste = Einf黦en +SelectAll = Alles ausw鋒len +InsertSpeaker = Sprecher einf黦en +InsertOneTime = Einmal einf黦en +InsertTwoTimes = Zweimal einf黦en +New = Neu +Open = 謋fnen +Close = Schlie遝n +Save = Speichern +SaveAs = Speichern als +Quit = Quit +Keyboard = Tastatur Eingabemethode +Preferences = Pr鋐erenzen +FindHeading = Search +FindReplaceHeading = Search and Replace +FindWhat = Find what +ReplaceWith = Replace with +ReplaceQ = Replace? +FindNextYesNo = Find next? +StartFromBeginning = You've reached the end of the document. Do you want to continue searching from the beginning? +TextFound = Text found. +Replace = Replace +ReplaceAll = Replace all +NoReplace = Don't replace +Cancel = Cancel \ No newline at end of file diff --git a/source/MessageBundle_zh_CN.properties b/source/MessageBundle_zh_CN.properties new file mode 100644 index 0000000..6e7084c --- /dev/null +++ b/source/MessageBundle_zh_CN.properties @@ -0,0 +1,34 @@ +Project = \u9879\u76ee +Speakers = \u5bf9\u8bdd\u8005 +TimeCoding = \u65f6\u95f4\u4ee3\u7801 +AdjustTimeCode = \u8c03\u6574\u65f6\u95f4 +In =\u5f00\u59cb +Out = \u7ed3\u675f +PlaySegment = \u663e\u793a\u7a97\u53e3 +NewProject =\u65e0\u65b0\u9879\u76ee\u6587\u4ef6 +TitleColon = \u9898\u76ee +TypeNewTitleColon = \u65b0\u9898\u76ee +NoMedia = \u65e0\u5a92\u4f53\u6587\u4ef6 +MediaColon = \u5a92\u4f53 +NoTranscript = \u65e0\u6587\u672c\u6587\u4ef6 +TranscriptColon = \u6587\u5b57 +KeyboardInputMethod = \u952e\u76d8\u5e03\u5c40 +TranscriberName = \u8bb0\u5f55\u8005 +TranscriberTask = \u8bb0\u5f55\u5185\u5bb9 +Add = \u589e\u52a0 +FaceColon = \u9009\u62e9\u8138\u5f62 +NameColon = \u53d6\u540d +EnterNewSpeakerInfo = \u589e\u52a0\u65b0\u7528\u6237\u7a97\u53e3 +Edit = \u7f16\u8f91 +EditSpeakerInfo = \u7f16\u8f91\u7a97\u53e3 +Remove = \u5220\u9664 +SureDeleteSpeaker = \u786e\u5b9e\u5220\u9664\u5417\uff1f +Warning = \u8b66\u544a\uff01 +Face = \u8138 +Name = \u540d +SaveCurrent = \u4fdd\u5b58 +OpenExisting =\u6253\u5f00 +WhatToDo =\u9009\u62e9 +ChooseOne =\u9009\u62e9\u4e4b\u4e00 +Play = \u64ad\u653e +Pause = \u6682\u505c diff --git a/source/chinesebundle.txt b/source/chinesebundle.txt new file mode 100644 index 0000000..b4c2d82 --- /dev/null +++ b/source/chinesebundle.txt @@ -0,0 +1,34 @@ +Project = 项目 +Speakers = 对话者 +TimeCoding = 时间代码 +AdjustTimeCode = 调整时间 +In =开始 +Out = 结束 +PlaySegment = 显示窗口 +NewProject =无新项目文件 +TitleColon = 题目 +TypeNewTitleColon = 新题目 +NoMedia = 无媒体文件 +MediaColon = 媒体 +NoTranscript = 无文本文件 +TranscriptColon = 文字 +KeyboardInputMethod = 键盘布局 +TranscriberName = 记录者 +TranscriberTask = 记录内容 +Add = 增加 +FaceColon = 选择脸形 +NameColon = 取名 +EnterNewSpeakerInfo = 增加新用户窗口 +Edit = 编辑 +EditSpeakerInfo = 编辑窗口 +Remove = 删除 +SureDeleteSpeaker = 确实删除吗? +Warning = 警告! +Face = 脸 +Name = 名 +SaveCurrent = 保存 +OpenExisting =打开 +WhatToDo =选择 +ChooseOne =选择之一 +Play = 播放 +Pause = 暂停 \ No newline at end of file diff --git a/source/org/thdl/quilldriver/QD.java b/source/org/thdl/quilldriver/QD.java new file mode 100644 index 0000000..508b964 --- /dev/null +++ b/source/org/thdl/quilldriver/QD.java @@ -0,0 +1,1651 @@ +package org.thdl.quilldriver; + +import java.util.*; +import java.io.*; +import java.net.*; +import javax.swing.*; +import javax.swing.table.*; +import javax.swing.event.*; +import javax.swing.text.*; +import javax.swing.plaf.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.dnd.*; +import java.awt.datatransfer.*; +import org.thdl.tib.input.*; +import org.thdl.tib.text.*; +import org.thdl.tib.text.TibetanDocument.*; + +import org.jdom.*; +import org.jdom.input.SAXBuilder; +import org.jdom.output.XMLOutputter; +import org.jdom.transform.JDOMSource; +import javax.xml.transform.stream.*; +import javax.xml.transform.*; + + +public class QD extends JDesktopPane { + //project related data + protected Project project; + + //speaker related + protected SpeakerTable speakerTable; + + //video related + protected QDPlayer player = null; + + //frame related + protected JInternalFrame videoFrame = null; + protected JInternalFrame textFrame = null; + protected JInternalFrame actionFrame = null; + + //miscellaneous stuff + protected JFileChooser fileChooser = null; + public JTabbedPane jtp; + public TimeCodeManager tcp = null; + public SpeakerManager spm = null; + public JTextPane pane; + public Hashtable actions; + public ImageIcon clockIcon; + public static final String componentStyleName = "Component"; + public Style componentStyle; + public DataFlavor timeFlavor; + + protected JMenu editMenu; + + protected ResourceBundle messages; + + protected java.util.List work; + protected Work currentWork; + + protected DuffPane sharedDP = new DuffPane(); + protected DuffPane sharedDP2 = new DuffPane(); + + protected TibetanDocument findDoc = null; + protected TibetanDocument replaceDoc = null; + +protected URL keyboard_url = null; + + +public QD(ResourceBundle messages) { + this.messages = messages; + + setBackground(new JFrame().getBackground()); + setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); + + clockIcon = new ImageIcon(QD.class.getResource("clock.gif")); + timeFlavor = new DataFlavor(Integer.class, "time"); + + fileChooser = new JFileChooser(); + fileChooser.addChoosableFileFilter(new XMLFilter()); + + Action insert1TimeAction = new AbstractAction("insert1Time", null) { + public void actionPerformed(ActionEvent e) { + new TimePoint(pane, clockIcon, tcp.getOutTime()); + tcp.setInTime(tcp.getOutTime().intValue()); + tcp.setOutTime(player.getLastTime()); + } + }; + + Action insert2TimesAction = new AbstractAction("insert2Times", null) { + public void actionPerformed(ActionEvent e) { + int p1 = pane.getSelectionStart(); + int p2 = pane.getSelectionEnd(); + pane.setCaretPosition(p1); + new TimePoint(pane, clockIcon, tcp.getInTime()); + pane.setCaretPosition(p2+1); + new TimePoint(pane, clockIcon, tcp.getOutTime()); + if (p1 == p2) + pane.setCaretPosition(pane.getCaretPosition()-1); + tcp.setInTime(tcp.getOutTime().intValue()); + tcp.setOutTime(player.getLastTime()); + } + }; + + Action saveAction = new AbstractAction("saveTranscript", null) { + public void actionPerformed(ActionEvent e) { + getSave(); + } + }; + + JTextPane tp = new JTextPane(); + Keymap keymap = tp.addKeymap("QDBindings", tp.getKeymap()); + + KeyStroke insert1TimeKey = KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, Event.CTRL_MASK); + KeyStroke insert2TimesKey = KeyStroke.getKeyStroke(KeyEvent.VK_CLOSE_BRACKET, Event.CTRL_MASK); + KeyStroke saveKey = KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK); + + keymap.addActionForKeyStroke(insert1TimeKey, insert1TimeAction); + keymap.addActionForKeyStroke(insert2TimesKey, insert2TimesAction); + keymap.addActionForKeyStroke(saveKey, saveAction); + + Speaker[] speakers = new Speaker[0]; + SpeakerData speakerData = new SpeakerData(speakers, keymap); + speakerTable = new SpeakerTable(speakerData); + + pane = new DuffPane(); + pane.setKeymap(keymap); + new TimePointDropTarget(pane); + + work = new ArrayList(); + currentWork = new Work(); + work.add(currentWork); + + JPanel textPanel = new JPanel(new BorderLayout()); + textPanel.add("Center", new JScrollPane(pane)); + + JPanel actionPanel = new JPanel(new BorderLayout()); + jtp = new JTabbedPane(); + project = null; + spm = new SpeakerManager(speakerTable); + jtp.addTab(messages.getString("Speakers"), spm); + actionPanel.add("Center", jtp); + + //(String title, boolean resizable, boolean closable, boolean maximizable, boolean iconifiable) + videoFrame = new JInternalFrame(null, false, false, false, false); + videoFrame.setVisible(true); + videoFrame.setLocation(0,0); + videoFrame.setSize(0,0); + add(videoFrame, JLayeredPane.POPUP_LAYER); + invalidate(); + validate(); + repaint(); + + textFrame = new JInternalFrame(null, false, false, false, true); + textFrame.setVisible(true); + textFrame.setContentPane(textPanel); + textFrame.setLocation(0,0); + textFrame.setSize(0,0); + textFrame.setJMenuBar(getTextMenuBar()); + add(textFrame, JLayeredPane.DEFAULT_LAYER); + invalidate(); + validate(); + repaint(); + + actionFrame = new JInternalFrame(null, false, false, false, true); + actionFrame.setVisible(true); + actionFrame.setContentPane(actionPanel); + actionFrame.setLocation(0,0); + actionFrame.setSize(0,0); + add(actionFrame, JLayeredPane.DEFAULT_LAYER); + invalidate(); + validate(); + repaint(); + + addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent ce) { + Dimension d = videoFrame.getSize(); + if (d.width == 0 && d.height == 0) + videoFrame.setSize(getSize().width / 2, 0); + textFrame.setLocation(videoFrame.getSize().width, 0); + textFrame.setSize(getSize().width - videoFrame.getSize().width, getSize().height); + actionFrame.setLocation(0, videoFrame.getSize().height); + actionFrame.setSize(videoFrame.getSize().width, getSize().height - videoFrame.getSize().height); + } + }); +} + +private void startTimer() { + final java.util.Timer timer = new java.util.Timer(true); + timer.schedule(new TimerTask() { + public void run() + { + if (player.cmd_isSized()) + { + timer.cancel(); + + if (tcp != null) + jtp.remove(tcp); + tcp = new TimeCodeManager(); + jtp.addTab(messages.getString("TimeCoding"), tcp); + + videoFrame.setContentPane(player); + videoFrame.pack(); + videoFrame.setMaximumSize(videoFrame.getSize()); + invalidate(); + validate(); + repaint(); + textFrame.setLocation(videoFrame.getSize().width, 0); + textFrame.setSize(getSize().width - videoFrame.getSize().width, getSize().height); + invalidate(); + validate(); + repaint(); + actionFrame.setLocation(0, videoFrame.getSize().height); + actionFrame.setSize(videoFrame.getSize().width, getSize().height - videoFrame.getSize().height); + invalidate(); + validate(); + repaint(); + } + }}, 0, 50); +} + +private void createActionTable(JTextComponent textComponent) { + actions = new Hashtable(); + Action[] actionsArray = textComponent.getActions(); + for (int i = 0; i < actionsArray.length; i++) { + Action a = actionsArray[i]; + actions.put(a.getValue(Action.NAME), a); + } +} + +private Action getActionByName(String name) { + return (Action)(actions.get(name)); +} + +class TimePoint extends JLabel implements DragGestureListener, DragSourceListener { + StyledDocument doc; + Position pos; + Integer time; + + TimePoint(final JTextPane tp, Icon icon, Integer time) { + super(icon); + this.time = time; + setCursor(new Cursor(Cursor.HAND_CURSOR)); + setToolTipText(getTimeAsString()); + DragSource dragSource = DragSource.getDefaultDragSource(); + dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this); + addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1) + playSegment(); + else { + SpinnerNumberModel snm1 = new SpinnerNumberModel(0, 0, player.getLastTime(), 10); + JSpinner spinner = new JSpinner(snm1); + spinner.setPreferredSize(new Dimension(100, 40)); + spinner.setValue(getTime()); + if (JOptionPane.showOptionDialog(tp, spinner, messages.getString("AdjustTimeCode"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null) == JOptionPane.OK_OPTION) + setTime((Integer)spinner.getValue()); + } + } + }); + doc = tp.getStyledDocument(); + tp.insertComponent(this); + try { //insertions occur prior to position, so position should be right before icon after icon is inserted + pos = doc.createPosition(tp.getCaretPosition()-1); + } catch (BadLocationException ble) { + ble.printStackTrace(); + } + } + public void setTime(Integer t) { + time = t; + setToolTipText(getTimeAsString()); + } + public Integer getTime() { + return time; + } + public String getTimeAsString() { + return String.valueOf(time); + } + public void playSegment() { + int i=pos.getOffset(); + System.out.println(String.valueOf(i)); + for (i++; i in.intValue()) + player.cmd_play(in, out); + } + }); + JPanel ps = new JPanel(); + ps.add(playSegButton); + +/* + JButton playButton = new JButton(messages.getString("Play")); + JButton pauseButton = new JButton(messages.getString("Pause")); + + playButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (player != null) + player.cmd_play(); + } + }); + pauseButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (player != null) + player.cmd_stop(); + } + }); +*/ + + Box box = Box.createVerticalBox(); + box.add(inPanel); + box.add(outPanel); + box.add(ps); + + add("North", box); + } + public Integer getInTime() { + return (Integer)inSpinner.getValue(); + } + public Integer getOutTime() { + return (Integer)outSpinner.getValue(); + } + public void setInTime(int k) { + inSpinner.setValue(new Integer(k)); + } + public void setOutTime(int k) { + outSpinner.setValue(new Integer(k)); + } +} + +class Work { + public String name; + public String task; + public String startDate; + public String duration; + public Date beginTime; + + Work() { + beginTime = new Date(); + startDate = beginTime.toString(); + } + public void stopWork() { + Date stopTime = new Date(); + long milliseconds = stopTime.getTime() - beginTime.getTime(); + int minutes = new Long(milliseconds / 1000 / 60).intValue(); + duration = String.valueOf(minutes); + name = project.getTranscriberName(); + task = project.getTranscriberTask(); + } +} + +class Project extends JPanel { + JTextField titleField, mediaField, transcriptField, nameField, taskField; + File transcript = null; + File media = null; + +public String getTitle() { + return titleField.getText(); +} +public void setTitle(String s) { + titleField.setText(s); +} +public String getTranscriberName() { + return nameField.getText(); +} +public void setTranscriberName(String s) { + nameField.setText(s); +} +public String getTranscriberTask() { + return taskField.getText(); +} +public void setTranscriberTask(String s) { + taskField.setText(s); +} +public File getTranscript() { + return transcript; +} +public void setTranscript(File f) { //doesn't actually load or save transcript, just changes changeTranscript label + transcript = f; + if (transcript == null) + transcriptField.setText(""); + else + transcriptField.setText(transcript.getPath()); +} +public File getMedia() { + return media; +} +public void setMedia(File f) { + if (f == null) { + media = f; + mediaField.setText(media.getPath()); + if (player != null) { + player.cmd_stop(); + player.destroy(); + videoFrame.getContentPane().remove(player); + videoFrame.getContentPane().invalidate(); + videoFrame.getContentPane().validate(); + videoFrame.getContentPane().repaint(); + player = null; + videoFrame.setSize(new Dimension(QD.this.getSize().width / 2, 0)); + jtp.remove(tcp); + tcp = null; + actionFrame.setLocation(0,0); + actionFrame.setSize(new Dimension(actionFrame.getSize().width, QD.this.getSize().height)); + } + } + else { + try { + URL url = f.toURL(); + + if (player != null) { + player.cmd_stop(); + player.destroy(); + } + player = new QDPlayer(QD.this, url); + media = f; + mediaField.setText(media.getPath()); + startTimer(); + } catch (MalformedURLException murle) { + murle.printStackTrace(); + } + } +} + +public Project() { + JPanel p = new JPanel(new GridLayout(2,2)); + titleField = new JTextField(); + int preferredHeight = titleField.getPreferredSize().height; + titleField.setPreferredSize(new Dimension(300, preferredHeight)); + mediaField = new JTextField(); + mediaField.setPreferredSize(new Dimension(300, preferredHeight)); + mediaField.setEditable(false); + transcriptField = new JTextField(); + transcriptField.setPreferredSize(new Dimension(300, preferredHeight)); + transcriptField.setEditable(false); + nameField = new JTextField(); + nameField.setPreferredSize(new Dimension(300, preferredHeight)); + taskField = new JTextField(); + taskField.setPreferredSize(new Dimension(300, preferredHeight)); + + Box box = Box.createVerticalBox(); + JPanel p1 = new JPanel(); + p1.add(new JLabel(messages.getString("TitleColon"))); + p1.add(titleField); + JPanel p1b = new JPanel(new BorderLayout()); + p1b.add("East", p1); + p1b.setAlignmentX(Component.RIGHT_ALIGNMENT); + + JPanel p2 = new JPanel(); + p2.add(new JLabel(messages.getString("MediaColon"))); + p2.add(mediaField); + JPanel p2b = new JPanel(new BorderLayout()); + p2b.add("East", p2); + p2b.setAlignmentX(Component.RIGHT_ALIGNMENT); + + JPanel p3 = new JPanel(); + p3.add(new JLabel(messages.getString("TranscriptColon"))); + p3.add(transcriptField); + JPanel p3b = new JPanel(new BorderLayout()); + p3b.add("East", p3); + p3b.setAlignmentX(Component.RIGHT_ALIGNMENT); + + JPanel p4 = new JPanel(); + p4.add(new JLabel(messages.getString("TranscriberName"))); + p4.add(nameField); + JPanel p4b = new JPanel(new BorderLayout()); + p4b.add("East", p4); + p4b.setAlignmentX(Component.RIGHT_ALIGNMENT); + + JPanel p5 = new JPanel(); + p5.add(new JLabel(messages.getString("TranscriberTask"))); + p5.add(taskField); + JPanel p5b = new JPanel(new BorderLayout()); + p5b.add("East", p5); + p5b.setAlignmentX(Component.RIGHT_ALIGNMENT); + + box.add(p1b); + box.add(p2b); + box.add(p3b); + box.add(p4b); + box.add(p5b); + + JPanel pBig = new JPanel(new BorderLayout()); + pBig.add("West", box); + + setLayout(new BorderLayout()); + add("North", pBig); +} +} + +public void changeKeyboard(ActionEvent e) { + DuffPane dp = (DuffPane)pane; + if (e.getActionCommand().equals("wylie")) { + dp.registerKeyboard(); + // project.tName.setupKeyboard(); + // project.tTask.setupKeyboard(); + sharedDP.setupKeyboard(); + sharedDP2.setupKeyboard(); + return; + } + keyboard_url = null; + if (e.getActionCommand().equals("sambhota1")) + keyboard_url = TibetanMachineWeb.class.getResource("sambhota_keyboard_1.ini"); + else if (e.getActionCommand().equals("tcc1")) + keyboard_url = TibetanMachineWeb.class.getResource("tcc_keyboard_1.ini"); + else if (e.getActionCommand().equals("tcc2")) + keyboard_url = TibetanMachineWeb.class.getResource("tcc_keyboard_2.ini"); + dp.registerKeyboard(keyboard_url); +// project.tName.setupKeyboard(); +// project.tTask.setupKeyboard(); + sharedDP.setupKeyboard(); + sharedDP2.setupKeyboard(); +} + +public boolean getSave() { + if (pane.getDocument().getLength() == 0 && speakerTable.getRowCount() == 0) + return true; //nothing to save + + if (project.getTranscript() == null) { + if (project.getMedia() == null) + fileChooser.setSelectedFile(null); + else { + String path = project.getMedia().getPath(); + path = path.substring(0, path.lastIndexOf('.')) + ".xml"; + fileChooser.setSelectedFile(new File(path)); + } + if (fileChooser.showSaveDialog(QD.this) == JFileChooser.APPROVE_OPTION) { + File f = fileChooser.getSelectedFile(); + project.setTranscript(f); + } else + return false; + } + currentWork.stopWork(); + +//change keyboard back to wylie for a second + DuffPane dp = (DuffPane)pane; +if (keyboard_url != null) { + + dp.registerKeyboard(); + // project.tName.setupKeyboard(); + // project.tTask.setupKeyboard(); + sharedDP.setupKeyboard(); + sharedDP.setupKeyboard(); +} + + + org.jdom.Element title = new org.jdom.Element("title"); + title.setText(project.getTitle().trim()); + + org.jdom.Element media = new org.jdom.Element("mediafile"); + if (project.getMedia() == null) + media.setText(""); + else { + String tPath = project.getTranscript().getPath(); + String mPath = project.getMedia().getPath(); + if (tPath.substring(0, tPath.lastIndexOf(File.separatorChar)).equals(mPath.substring(0, mPath.lastIndexOf(File.separatorChar)))) + media.setText(mPath.substring(mPath.lastIndexOf(File.separatorChar)+1)); + else + media.setText(mPath); + } + + org.jdom.Element speakers = new org.jdom.Element("speakers"); + SpeakerData sd = (SpeakerData)speakerTable.getModel(); + java.util.List allSpeakers = sd.getSpeakers(); + Iterator spIter = allSpeakers.iterator(); + while (spIter.hasNext()) { + Speaker sp = (Speaker)spIter.next(); + org.jdom.Element speaker = new org.jdom.Element("speaker"); + speaker.setAttribute("iconid", String.valueOf(sp.getIconID())); + speaker.setText(sp.getName()); + speakers.addContent(speaker); + } + + org.jdom.Element works = new org.jdom.Element("workhistory"); + Iterator wkIter = work.iterator(); + while (wkIter.hasNext()) { + Work wkUnit = (Work)wkIter.next(); + org.jdom.Element wk = new org.jdom.Element("work"); + org.jdom.Element name = new org.jdom.Element("name"); + name.setText(wkUnit.name); + org.jdom.Element task = new org.jdom.Element("task"); + task.setText(wkUnit.task); + org.jdom.Element date = new org.jdom.Element("start"); + date.setText(wkUnit.startDate); + org.jdom.Element duration = new org.jdom.Element("duration"); + duration.setText(wkUnit.duration); + wk.addContent(name); + wk.addContent(task); + wk.addContent(date); + wk.addContent(duration); + works.addContent(wk); + } + + org.jdom.Element meta = new org.jdom.Element("metadata"); + meta.addContent(title); + meta.addContent(media); + meta.addContent(speakers); + meta.addContent(works); + + org.jdom.Element text = new org.jdom.Element("text"); + TibetanDocument doc = (TibetanDocument)pane.getDocument(); + ImageIcon[] icons = sd.getSpeakerIcons(); + int lastPoint = 0; + int k; + for (k=0; k 0) + dp.setText(""); + java.util.List textContent = text.getContent(); + ImageIcon[] icons = sd.getSpeakerIcons(); + Iterator textIter = textContent.iterator(); + boolean wasLastComponent = true; + while (textIter.hasNext()) { + Object nextContent = textIter.next(); + if (nextContent instanceof org.jdom.Text) { + String wylie = ((org.jdom.Text)nextContent).getText(); + dp.toTibetanMachineWeb(wylie, tDoc.getLength()); + wasLastComponent = false; + } + else if (nextContent instanceof org.jdom.Element) { + org.jdom.Element e = (org.jdom.Element)nextContent; + dp.setCaretPosition(tDoc.getLength()); + if (e.getName().equals("time")) { +/* if (!wasLastComponent) + try { + tDoc.insertString(tDoc.getLength(), "\n", null); + } catch (BadLocationException ble) { + ble.printStackTrace(); + } +*/ + new TimePoint(dp, clockIcon, Integer.valueOf(e.getAttributeValue("t"))); + wasLastComponent = true; + } + else if (e.getName().equals("who")) { +/* if (!wasLastComponent) + try { + tDoc.insertString(tDoc.getLength(), "\n", null); + } catch (BadLocationException ble) { + ble.printStackTrace(); + } +*/ + dp.insertComponent(new JLabel(" ", icons[Integer.parseInt(e.getAttributeValue("id"))], SwingConstants.LEFT)); + wasLastComponent = true; + } + } + } + currentWork = new Work(); + work.add(currentWork); + +if (keyboard_url != null) { + dp.registerKeyboard(keyboard_url); + // project.tName.setupKeyboard(); + // project.tTask.setupKeyboard(); + sharedDP.setupKeyboard(); + sharedDP2.setupKeyboard(); +} + +project.setTranscript(t); + + return true; + } catch (JDOMException jdome) { + jdome.printStackTrace(); + return false; + } +} + +class SpeakerManager extends JPanel { + JPanel top; + boolean isEditable; + +//public JPanel getSpeakerManager(final SpeakerTable sTable) { + +SpeakerManager(final SpeakerTable sTable) { + + setLayout(new BorderLayout()); + + JButton addButton = new JButton(messages.getString("Add")); + addButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + SpeakerData sd = (SpeakerData)sTable.getModel(); + JPanel p0 = new JPanel(new GridLayout(0,1)); + JPanel p1 = new JPanel(); + p1.add(new JLabel(messages.getString("FaceColon") + " ")); + JComboBox combo = new JComboBox(sd.getSpeakerIcons()); + p1.add(combo); + JPanel p2 = new JPanel(); + p2.add(new JLabel(messages.getString("NameColon") + " ")); + sharedDP.setText(""); + sharedDP.setPreferredSize(new Dimension(250,50)); + p2.add(sharedDP); + p0.add(p1); + p0.add(p2); + if (JOptionPane.showConfirmDialog(SpeakerManager.this, p0, messages.getString("EnterNewSpeakerInfo"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) == JOptionPane.OK_OPTION) { + TibetanDocument doc = (TibetanDocument)sharedDP.getDocument(); + sd.addSpeaker(new Speaker(combo.getSelectedIndex(), doc.getWylie())); + } + } + }); + JButton editButton = new JButton(messages.getString("Edit")); + editButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int row = sTable.getSelectedRow(); + if (row == -1) + return; + SpeakerData sd = (SpeakerData)sTable.getModel(); + Speaker sp = sd.getSpeakerAt(row); + JPanel p0 = new JPanel(new GridLayout(0,1)); + JPanel p1 = new JPanel(); + p1.add(new JLabel(messages.getString("FaceColon") + " ")); + JComboBox combo = new JComboBox(sd.getSpeakerIcons()); + combo.setSelectedIndex(sp.getIconID()); + ImageIcon[] icons = sd.getSpeakerIcons(); + ImageIcon oldIcon = icons[sp.getIconID()]; + p1.add(combo); + JPanel p2 = new JPanel(); + p2.add(new JLabel(messages.getString("NameColon") + " ")); + sharedDP.setText(""); + sharedDP.setPreferredSize(new Dimension(250,50)); + sharedDP.toTibetanMachineWeb(sp.getName(), 0); + p2.add(sharedDP); + p0.add(p1); + p0.add(p2); + if (JOptionPane.showConfirmDialog(SpeakerManager.this, p0, messages.getString("EditSpeakerInfo"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) == JOptionPane.OK_OPTION) { + sd.setValueAt(new Integer(combo.getSelectedIndex()), row, 0); + TibetanDocument doc = (TibetanDocument)sharedDP.getDocument(); + sd.setValueAt(doc.getWylie(), row, 1); + if (!oldIcon.equals(icons[combo.getSelectedIndex()])) { + DefaultStyledDocument doc2 = (DefaultStyledDocument)pane.getDocument(); + int k = pane.getCaretPosition(); + for (int i=0; i -1 && JOptionPane.showConfirmDialog(SpeakerManager.this, messages.getString("SureDeleteSpeaker"), messages.getString("Warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { + SpeakerData sd = (SpeakerData)sTable.getModel(); + Speaker sp = sd.getSpeakerAt(row); + ImageIcon[] icons = sd.getSpeakerIcons(); + DefaultStyledDocument doc = (DefaultStyledDocument)pane.getDocument(); + int k2 = doc.getLength(); + for (int i=0; i 0) { + DefaultStyledDocument doc = (DefaultStyledDocument)tp.getDocument(); + AttributeSet attr = doc.getCharacterElement(pos-1).getAttributes(); + Component comp; + if (null != (comp = StyleConstants.getComponent(attr))) + if (comp instanceof JLabel) { + JLabel l = (JLabel)comp; + ImageIcon ic = (ImageIcon)l.getIcon(); + if (iconMap.containsKey(ic)) { + Speaker sp = (Speaker)iconMap.get(ic); + int k = speakers.indexOf(sp) + 1; + if (k == speakers.size()) + k=0; + try { + tp.getDocument().remove(pos-1, 1); + sp = (Speaker)speakers.get(k); + tp.insertComponent(new JLabel(" ", spIcon[sp.getIconID()], SwingConstants.LEFT)); + return; + } catch (BadLocationException ble) { + ble.printStackTrace(); + } + } + } + } + Speaker sp = (Speaker)speakers.get(0); + tp.insertComponent(new JLabel(" ", spIcon[sp.getIconID()], SwingConstants.LEFT)); + } + }; + KeyStroke insertSpeakerKey = KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.ALT_MASK); + keymap.addActionForKeyStroke(insertSpeakerKey, insertSpeakerAction); + } + public boolean addSpeaker(Speaker speaker) { + if (iconMap.containsKey(spIcon[speaker.getIconID()])) + return false; + else { + iconMap.put(spIcon[speaker.getIconID()], speaker); + speakers.add(speaker); + fireTableRowsInserted(speakers.size()-1, speakers.size()-1); + return true; + } + } + public Speaker getSpeakerAt(int row) { + if (row > -1 && row < speakers.size()) + return ((Speaker)speakers.get(row)); + return null; + } + public java.util.List getSpeakers() { + return speakers; + } + public ImageIcon[] getSpeakerIcons() { + return spIcon; + } + public Speaker getSpeakerForIcon(Icon icon) { + if (iconMap.containsKey(icon)) + return (Speaker)iconMap.get(icon); + else + return null; + } + public void removeAllSpeakers() { + speakers.clear(); + iconMap.clear(); + } + public void removeSpeaker(int row) + { + if (row > -1 && row < speakers.size()) + { + Speaker sp = getSpeakerAt(row); + iconMap.remove(spIcon[sp.getIconID()]); + speakers.remove(row); + fireTableRowsDeleted(row,row); + } + } + public int getRowCount() + { + return speakers.size(); + } + public int getColumnCount() + { + return 2; + } + public Class getColumnClass(int c) + { + return getValueAt(0, c).getClass(); + } + public Object getValueAt(int row, int column) + { + Speaker sp = (Speaker)speakers.get(row); + if (column == 0) + return spIcon[sp.getIconID()]; + try { //otherwise column 1, the speaker name + return TibetanDocument.getTibetanMachineWeb(sp.getName().trim()); + } catch (InvalidWylieException iwe) { + iwe.printStackTrace(); + return null; + } + } + public void setValueAt(Object object, int row, int column) { + Speaker sp = (Speaker)speakers.get(row); + if (column == 0 && object instanceof Integer) { + Integer bigInt = (Integer)object; + int k = bigInt.intValue(); + if (!iconMap.containsKey(spIcon[k])) { + iconMap.remove(spIcon[sp.getIconID()]); + iconMap.put(spIcon[k], sp); + sp.setIconID(k); + } + } else if (object instanceof String) { + String wylie = (String)object; + sp.setName(wylie); + } + fireTableCellUpdated(row, column); + } +} + +class SpeakerTable extends JTable +{ + private TableCellRenderer duffRenderer, normalRenderer; + private SpeakerData speakerData; + + public SpeakerTable(SpeakerData speakerData) + { + this.speakerData = speakerData; + this.setModel(this.speakerData); + this.setRowHeight(55); + this.setColumnSelectionAllowed(false); + this.setRowSelectionAllowed(true); + + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + TableColumnModel tcm = this.getColumnModel(); + duffRenderer = new DuffCellRenderer(); + + TableColumn tc = tcm.getColumn(0); + tc.setResizable(false); + tc.setMaxWidth(60); + tc.setMinWidth(60); + tc.setHeaderValue(messages.getString("Face")); + + tc = tcm.getColumn(1); + tc.setCellRenderer(duffRenderer); + tc.setHeaderValue(messages.getString("Name")); + } +} + +public JMenuBar getTextMenuBar() { + JMenu modeMenu = new JMenu(messages.getString("Mode")); + JRadioButton editButton = new JRadioButton(messages.getString("Edit")); + JRadioButton viewButton = new JRadioButton(messages.getString("ReadOnly")); + editButton.setActionCommand("edit"); + viewButton.setActionCommand("view"); + RadioListener l = new RadioListener(); + editButton.addActionListener(l); + viewButton.addActionListener(l); + editButton.setSelected(true); + ButtonGroup bg = new ButtonGroup(); + bg.add(editButton); + bg.add(viewButton); + JPanel buttons = new JPanel(new GridLayout(0,1)); + buttons.add(editButton); + buttons.add(viewButton); + modeMenu.add(buttons); + + JMenu viewMenu = new JMenu(messages.getString("View")); + JMenuItem previousItem = new JMenuItem(messages.getString("Previous")); + JMenuItem currentItem = new JMenuItem(messages.getString("Current")); + JMenuItem nextItem = new JMenuItem(messages.getString("Next")); + JMenuItem suppressTimesItem = new JMenuItem(messages.getString("SuppressTimes")); + viewMenu.add(previousItem); + viewMenu.add(currentItem); + viewMenu.add(nextItem); + viewMenu.addSeparator(); + viewMenu.add(suppressTimesItem); + + JMenu searchMenu = new JMenu(messages.getString("Search")); + JMenuItem findTextItem = new JMenuItem(messages.getString("FindText")); + findTextItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + findText(); + } + }); + + JMenuItem replaceTextItem = new JMenuItem(messages.getString("ReplaceText")); + replaceTextItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + replaceText(); + } + }); + + JMenuItem findspeakerItem = new JMenuItem(messages.getString("FindSpeaker")); + JMenuItem findtimeItem = new JMenuItem(messages.getString("FindTime")); + searchMenu.add(findTextItem); + searchMenu.add(replaceTextItem); + searchMenu.addSeparator(); + searchMenu.add(findspeakerItem); + searchMenu.add(findtimeItem); + + editMenu = new JMenu(messages.getString("Edit")); + JMenuItem cutItem = new JMenuItem(messages.getString("Cut")); + JMenuItem copyItem = new JMenuItem(messages.getString("Copy")); + JMenuItem pasteItem = new JMenuItem(messages.getString("Paste")); + JMenuItem selectallItem = new JMenuItem(messages.getString("SelectAll")); + JMenuItem insertspeakerItem = new JMenuItem(messages.getString("InsertSpeaker")); + JMenuItem insertonetimeItem = new JMenuItem(messages.getString("InsertOneTime")); + JMenuItem inserttwotimesItem = new JMenuItem(messages.getString("InsertTwoTimes")); + editMenu.add(cutItem); + editMenu.add(copyItem); + editMenu.add(pasteItem); + editMenu.add(selectallItem); + editMenu.addSeparator(); + editMenu.add(insertspeakerItem); + editMenu.add(insertonetimeItem); + editMenu.add(inserttwotimesItem); + + JMenuBar bar = new JMenuBar(); + bar.add(modeMenu); + bar.add(viewMenu); + bar.add(searchMenu); + bar.add(editMenu); + return bar; +} + +public int findNextText(int startPos, TibetanDocument sourceDoc, TibetanDocument findDoc) { + if (startPos<0 || startPos>sourceDoc.getLength()-1) + return -1; + +try { + + AttributeSet firstAttr = findDoc.getCharacterElement(0).getAttributes(); + String firstFontName = StyleConstants.getFontFamily(firstAttr); + char firstSearchChar = findDoc.getText(0,1).charAt(0); + + boolean match = false; + for (int i=startPos; i0) { //found!! so highlight text and seek video + if (startingOver && i>pos.getOffset()-1) + break; + pane.setSelectionStart(i); + pane.setSelectionEnd(i+findDoc.getLength()); + if (JOptionPane.showInternalConfirmDialog(textFrame, messages.getString("FindNextYesNo"), null, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) != JOptionPane.YES_OPTION) + break; + i++; + } + if (i<0 || i==doc.getLength() && pos.getOffset()>0) { //reached end of document - start over? + if (startingOver || pos.getOffset()==0) + break; + if (JOptionPane.showInternalConfirmDialog(textFrame, messages.getString("StartFromBeginning"), null, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) != JOptionPane.YES_OPTION) + break; + i=0; + startingOver = true; + } + } + } catch (BadLocationException ble) { + ble.printStackTrace(); + } + + } +} + +public void replaceText() { + //get input from user on what to search for + JPanel p0 = new JPanel(new GridLayout(0,1)); + JPanel p2 = new JPanel(); + p2.add(new JLabel(messages.getString("FindWhat") + " ")); + if (findDoc == null) { + sharedDP.setText(""); + findDoc = (TibetanDocument)sharedDP.getDocument(); + } else + sharedDP.setDocument(findDoc); + sharedDP.setPreferredSize(new Dimension(250,50)); + p2.add(sharedDP); + JPanel p3 = new JPanel(); + p3.add(new JLabel(messages.getString("ReplaceWith") + " ")); + if (replaceDoc == null) { + sharedDP2.setText(""); + replaceDoc = (TibetanDocument)sharedDP2.getDocument(); + } else + sharedDP2.setDocument(replaceDoc); + sharedDP2.setPreferredSize(new Dimension(250,50)); + p3.add(sharedDP2); + + p0.add(p2); + p0.add(p3); + + if (JOptionPane.showConfirmDialog(textFrame, p0, messages.getString("FindReplaceHeading"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) == JOptionPane.OK_OPTION) { + + try { + java.util.List replaceDCs = new ArrayList(); + for (int k=0; k0) { //found!! so highlight text and seek video + if (startingOver && i>pos.getOffset()-1) + break; + if (replaceAll) { + doc.remove(i,findDoc.getLength()); + doc.insertDuff(i,dd); + } else { + pane.setSelectionStart(i); + pane.setSelectionEnd(i+findDoc.getLength()); + String choice = (String)JOptionPane.showInternalInputDialog(textFrame, messages.getString("ReplaceQ"), null, JOptionPane.PLAIN_MESSAGE, null, replaceOptions, replaceOptions[0]); + if (choice == null) //cancel, so stop searching + break outer; + if (choice.equals(replaceOptions[0])) { //replace + doc.remove(i,findDoc.getLength()); + doc.insertDuff(i,dd); + } + else if (choice.equals(replaceOptions[1])) { //replace all + doc.remove(i,findDoc.getLength()); + doc.insertDuff(i,dd); + replaceAll = true; + } + } + i++; + } + if (i<0 || i==doc.getLength() && pos.getOffset()>0) { //reached end of document - start over? + if (startingOver || pos.getOffset()==0) + break; + if (JOptionPane.showInternalConfirmDialog(textFrame, messages.getString("StartFromBeginning"), null, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) != JOptionPane.YES_OPTION) + break; + i=0; + startingOver = true; + } + } + } catch (BadLocationException ble) { + ble.printStackTrace(); + } + + } +} + +class RadioListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("edit")) { + //make the text pane editable + pane.setEditable(true); + + //reinstate the edit menu to the pane + textFrame.getJMenuBar().add(editMenu); + textFrame.invalidate(); + textFrame.validate(); + textFrame.repaint(); + + //add speaker-edit features + spm.setEditable(true); + + //add the time-coding tab + if (tcp != null) + jtp.addTab(messages.getString("TimeCoding"), tcp); + + //make the project details editable + if (project != null) +// project.setEditable(true); + + jtp.addTab(messages.getString("ProjectDetails"), project); + } + else if (e.getActionCommand().equals("view")) { + //make the text pane non-editable + pane.setEditable(false); + + //remove the edit menu from the pane + textFrame.getJMenuBar().remove(editMenu); + textFrame.invalidate(); + textFrame.validate(); + textFrame.repaint(); + + //remove speaker-edit features + spm.setEditable(false); + + //remove the time-coding tab + if (tcp != null) + jtp.remove(tcp); + + //make the project tab non-editable + if (project != null) + jtp.remove(project); +// project.setEditable(false); + } + } +} + + private class XMLFilter extends javax.swing.filechooser.FileFilter { + // accepts all directories and all savant files + + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } + + String fName = f.getName(); + int i = fName.lastIndexOf('.'); + + if (i < 0) + return false; + + else { + String ext = fName.substring(i+1).toLowerCase(); + + if (ext.equals("xml")) + return true; + else + return false; + } + } + + //the description of this filter + public String getDescription() { + return "Extensible Markup Language (.xml)"; + } + } +} diff --git a/source/org/thdl/quilldriver/QDPlayer.java b/source/org/thdl/quilldriver/QDPlayer.java new file mode 100644 index 0000000..5c061df --- /dev/null +++ b/source/org/thdl/quilldriver/QDPlayer.java @@ -0,0 +1,405 @@ +package org.thdl.quilldriver; + +import java.util.*; +import java.net.*; +import javax.media.*; +import java.awt.*; +import javax.swing.*; +import javax.swing.event.*; + +/*-----------------------------------------------------------------------*/ +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(); + return; + } catch (java.io.IOException ex) { + System.err.println("IO exception"); + ex.printStackTrace(); + 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. +> +> +> +> + +*/ \ No newline at end of file diff --git a/source/org/thdl/quilldriver/QDShell.java b/source/org/thdl/quilldriver/QDShell.java new file mode 100644 index 0000000..0c33cb8 --- /dev/null +++ b/source/org/thdl/quilldriver/QDShell.java @@ -0,0 +1,159 @@ +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.*; + +public class QDShell extends JFrame { + ResourceBundle messages = null; + QD qd = null; + +public static void main(String[] args) { + try { + PrintStream ps = new PrintStream(new FileOutputStream("qd.log")); + System.setErr(ps); + System.setOut(ps); + } + catch (Exception e) { + } + + Locale locale; + + if (args.length == 2) { + locale = new Locale(new String(args[0]), new String(args[1])); + Locale[] locales = Locale.getAvailableLocales(); + for (int k=0; k 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 void destroy() { + player.close(); + } + public void stop() { + player.stop(); + player.deallocate(); + } + public void start() { + openPlayer(); + } + private int getMinusStart(Vector v) { + int index = 0; + String first = (String)v.elementAt(index); + Float minus = (Float)hashStart.get(first); + for (int i=0;i f.floatValue()) { + minus = f; + index = i; + } + } + return index; + } + private int getMinusEnd(Vector v) { + int index = 0; + String first = (String)v.elementAt(index); + Float minus = (Float)hashEnd.get(first); + for (int i=0;i f.floatValue()) { + minus = f; + index = i; + } + } + return index; + } + public void addAnnotationPlayer(AnnotationPlayer ap) + { + listenerList.add(AnnotationPlayer.class, ap); + } + public void removeAnnotationPlayer(AnnotationPlayer ap) + { + listenerList.remove(AnnotationPlayer.class, ap); + } + 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_playFrom(String fromID) { + if (stillLoadingVideo) + return false; + + Float from = (Float)hashStart.get(fromID); +// String toID = (String)orderEndID.elementAt(orderEndID.size()-1); +// Float to = (Float)hashEnd.get(toID); + + if (play(from, null)) + return true; + else + return false; + } + + public boolean cmd_playS(String fromID) { + if (stillLoadingVideo) + return false; + + Float from = (Float)hashStart.get(fromID); + Float to = (Float)hashEnd.get(fromID); + if (play(from, to)) + return true; + else + return false; + } + public void cmd_nextEvent() { + Float when = new Float(when()); + if (!pileStart.empty()) { + String id = (String)pileStart.peek(); + Float f = (Float)hashStart.get(id); + if (when.floatValue() >= f.floatValue()) { + id = (String)pileStart.pop(); + fireStartAnnotation(id); + } + } + if (!pileEnd.empty()) { + String id = (String)pileEnd.peek(); + Float f = (Float)hashEnd.get(id); + if (when.floatValue() >= f.floatValue()) { + 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); + } + } + } + private void remplisPileStart(Float start, Float end) { + vide_Pile(); + pileStart.removeAllElements(); + pileEnd.removeAllElements(); + for (int i=orderEndID.size()-1; i!=-1; i--) { + String id = (String)orderEndID.elementAt(i); + Float f = (Float)hashEnd.get(id); + if ((f.floatValue() > start.floatValue()) && (f.floatValue() <= end.floatValue())) { + pileEnd.push(id); + } + } + for (int i=orderStartID.size()-1; i!=-1; i--) { + String id = (String)orderStartID.elementAt(i); + Float f = (Float)hashStart.get(id); + if ((f.floatValue() >= start.floatValue()) && (f.floatValue() < end.floatValue())) { + pileStart.push(id); + } + } + } + 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); + } + } +/*-----------------------------------------------------------------------*/ + private String when() { + if (player == null) + return "-1"; + if (player.getState() != Controller.Started) + return "-1"; + long currTime = player.getMediaNanoseconds(); + Float time = new Float(currTime); + float f = (time.floatValue() / 1000000000); + return Float.toString(f); + } + private boolean play(Float from, Float to) { + if (player == null) + return false; + final Time startTime = new Time((long)(from.floatValue() * 1000000000)); + 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((long)(to.floatValue() * 1000000000)); + 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(); + return; + } catch (java.io.IOException ex) { + System.err.println("IO exception"); + ex.printStackTrace(); + 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); + remplisPileStart(from, to); + 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(); + cmd_nextEvent(); + }}, 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); + + 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(); + } + } +}; \ No newline at end of file diff --git a/source/org/thdl/savant/TextHighlightPlayer.java b/source/org/thdl/savant/TextHighlightPlayer.java new file mode 100644 index 0000000..ab8e592 --- /dev/null +++ b/source/org/thdl/savant/TextHighlightPlayer.java @@ -0,0 +1,104 @@ +package org.thdl.savant; + +import java.awt.*; +import java.util.*; +import javax.swing.*; +import javax.swing.text.*; +import java.awt.event.MouseListener; + +public class TextHighlightPlayer extends JPanel implements AnnotationPlayer +{ + protected JTextComponent text; + protected Hashtable hashStart, hashEnd, highlights; + protected Highlighter highlighter; + protected Highlighter.HighlightPainter highlightPainter; + + public TextHighlightPlayer(TranscriptView view, Color highlightcolor) + { + text = view.getTextComponent(); + text.setEditable(false); + MouseListener[] mls = (MouseListener[])(text.getListeners(MouseListener.class)); + for (int i=0; i0 && next.charAt(0)!='-') + segBuffer.append(' '); + segBuffer.append(next); + } + doc.insertString(endPos.getOffset(), segBuffer.toString(), mas0); + } + startBuffer.append(thisStart); + startBuffer.append(','); + thisEnd = String.valueOf(endPos.getOffset()); + endBuffer.append(thisEnd); + endBuffer.append(','); + idBuffer.append("s0,"); + t1Buffer.append(current.getAttributeValue("start")); + t1Buffer.append(','); + t2Buffer.append(current.getAttributeValue("end")); + t2Buffer.append(','); + + while (iter.hasNext()) + { + current = (Element)iter.next(); + + while (current.getName().equals("spkr")) + { + doc.insertString(endPos.getOffset(), "\n\n", mas0); + doc.insertString(endPos.getOffset(), current.getAttributeValue("who"), mas); + + if (iter.hasNext()) + current = (org.jdom.Element)iter.next(); + } + + doc.insertString(endPos.getOffset(), "\n", mas0); + counter++; + thisStart = String.valueOf(endPos.getOffset()); + startBuffer.append(thisStart); + startBuffer.append(','); + if (current.getAttributeValue("gls").equals("PAUSE")) + doc.insertString(endPos.getOffset(), "......", mas0); + else { + String segString = current.getAttributeValue("seg"); + StringBuffer segBuffer = new StringBuffer(); + StringTokenizer segTokenizer = new StringTokenizer(segString); + for (int i=0; segTokenizer.hasMoreTokens(); i++) { + String next = segTokenizer.nextToken(); + if (i>0 && next.charAt(0)!='-') + segBuffer.append(' '); + segBuffer.append(next); + } + doc.insertString(endPos.getOffset(), segBuffer.toString(), mas0); + } + thisEnd = String.valueOf(endPos.getOffset()); + endBuffer.append(thisEnd); + endBuffer.append(','); + thisId = "s"+String.valueOf(counter); + idBuffer.append(thisId); + idBuffer.append(','); + t1Buffer.append(current.getAttributeValue("start")); + t1Buffer.append(','); + t2Buffer.append(current.getAttributeValue("end")); + t2Buffer.append(','); + } + + idBuffer.toString(); + t1Buffer.toString(); + t2Buffer.toString(); + startBuffer.toString(); + endBuffer.toString(); + } + catch (BadLocationException ble) + { + ble.printStackTrace(); + } + } + + public JTextComponent getTextComponent() + { + return text; + } + + public Document getDocument() + { + return xmlDoc; + } + + public String getIDs() + { + return idBuffer.toString(); + } + + public String getT1s() + { + return t1Buffer.toString(); + } + + public String getT2s() + { + return t2Buffer.toString(); + } + + public String getStartOffsets() + { + return startBuffer.toString(); + } + + public String getEndOffsets() + { + return endBuffer.toString(); + } +} \ No newline at end of file diff --git a/source/org/thdl/tib/text/DuffCellRenderer.java b/source/org/thdl/tib/text/DuffCellRenderer.java new file mode 100644 index 0000000..7955a38 --- /dev/null +++ b/source/org/thdl/tib/text/DuffCellRenderer.java @@ -0,0 +1,140 @@ +/* +The contents of this file are subject to the AMP 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 AMP web site +(http://www.tibet.iteso.mx/Guatemala/). + +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 Andres Montano Pellegrini. Portions +created by Andres Montano Pellegrini are Copyright 2001 Andres Montano +Pellegrini. All Rights Reserved. + +Contributor(s): Edward Garrett. +*/ + +package org.thdl.tib.text; + +import java.awt.*; +import javax.swing.*; +import javax.swing.table.TableCellRenderer; +import javax.swing.border.*; +import javax.swing.text.*; +import org.thdl.tib.input.DuffPane; +import org.thdl.tib.text.*; +import org.thdl.tib.text.TibetanDocument.DuffData; +import java.io.Serializable; + +/** Used by DictionaryTable to display a Tibetan word or phrase + (in either Roman or Tibetan script) in a single cell. + + @author Andrés Montano Pellegrini + @see DictionaryTable +*/ +public class DuffCellRenderer extends DuffPane implements TableCellRenderer, Serializable +{ + + protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); + + // We need a place to store the color the DuffPane should be returned + // to after its foreground and background colors have been set + // to the selection background color. + // These ivars will be made protected when their names are finalized. + private Color unselectedForeground; + private Color unselectedBackground; + + public DuffCellRenderer() + { + super(); + setOpaque(true); + setBorder(noFocusBorder); + } + + /** + * Overrides JComponent.setForeground to assign + * the unselected-foreground color to the specified color. + * + * @param c set the foreground color to this value + */ + public void setForeground(Color c) { + super.setForeground(c); + unselectedForeground = c; + } + + /** + * Overrides JComponent.setForeground to assign + * the unselected-background color to the specified color. + * + * @param c set the background color to this value + */ + public void setBackground(Color c) { + super.setBackground(c); + unselectedBackground = c; + } + + /** + * Notification from the UIManager that the look and feel + * [L&F] has changed. + * Replaces the current UI object with the latest version from the + * UIManager. + * + * @see JComponent#updateUI + */ + public void updateUI() { + super.updateUI(); + setForeground(null); + setBackground(null); + } + + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, boolean hasFocus, int row, int column) + { + if (isSelected) + { + super.setForeground(table.getSelectionForeground()); + super.setBackground(table.getSelectionBackground()); + } + else + { + super.setForeground((unselectedForeground != null) ? unselectedForeground : table.getForeground()); + super.setBackground((unselectedBackground != null) ? unselectedBackground : table.getBackground()); + } + + if (hasFocus) { + setBorder( UIManager.getBorder("Table.focusCellHighlightBorder") ); + if (table.isCellEditable(row, column)) { + super.setForeground( UIManager.getColor("Table.focusCellForeground") ); + super.setBackground( UIManager.getColor("Table.focusCellBackground") ); + } + } else { + setBorder(noFocusBorder); + } + + setValue(value); + + // ---- begin optimization to avoid painting background ---- + Color back = getBackground(); + boolean colorMatch = (back != null) && ( back.equals(table.getBackground()) ) && table.isOpaque(); + setOpaque(!colorMatch); + // ---- end optimization to aviod painting background ---- + + return this; + } + + public void setValue(Object value) + { + TibetanDocument doc = (TibetanDocument) getDocument(); + try + { + doc.remove(0, doc.getLength()); + } + catch (Exception e) + { + System.out.println(e); + } + doc.insertDuff(0, (DuffData []) value); + } +} \ No newline at end of file