fiore@3: /* fiore@3: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool fiore@3: fiore@3: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) fiore@3: fiore@3: This program is free software: you can redistribute it and/or modify fiore@3: it under the terms of the GNU General Public License as published by fiore@3: the Free Software Foundation, either version 3 of the License, or fiore@3: (at your option) any later version. fiore@3: fiore@3: This program is distributed in the hope that it will be useful, fiore@3: but WITHOUT ANY WARRANTY; without even the implied warranty of fiore@3: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fiore@3: GNU General Public License for more details. fiore@3: fiore@3: You should have received a copy of the GNU General Public License fiore@3: along with this program. If not, see . fiore@3: */ fiore@3: package uk.ac.qmul.eecs.ccmi.speech; fiore@3: fiore@3: import java.awt.event.ActionEvent; fiore@3: import java.awt.event.KeyEvent; fiore@3: fiore@3: import javax.swing.AbstractAction; fiore@3: import javax.swing.JTree; fiore@3: import javax.swing.KeyStroke; fiore@3: import javax.swing.tree.DefaultMutableTreeNode; fiore@3: import javax.swing.tree.TreePath; fiore@3: fiore@3: import uk.ac.qmul.eecs.ccmi.sound.PlayerListener; fiore@3: import uk.ac.qmul.eecs.ccmi.sound.SoundEvent; fiore@3: import uk.ac.qmul.eecs.ccmi.sound.SoundFactory; fiore@3: fiore@3: /** fiore@3: * fiore@3: */ fiore@3: @SuppressWarnings("serial") fiore@3: public class TreeSonifier { fiore@3: fiore@3: public void sonify(final JTree tree){ fiore@3: /* select the root node as selected */ fiore@3: tree.setSelectionRow(0); fiore@3: /* Overwrite keystrokes up,down,left,right arrows and space, shift, ctrl */ fiore@3: tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0),"down"); fiore@3: tree.getActionMap().put("down", new AbstractAction(){ fiore@3: @Override fiore@3: public void actionPerformed(ActionEvent evt) { fiore@3: DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); fiore@3: /* look if we've got a sibling node after (we are not at the bottom) */ fiore@3: DefaultMutableTreeNode nextTreeNode = treeNode.getNextSibling(); fiore@3: SoundEvent loop = null; fiore@3: if(nextTreeNode == null){ fiore@3: DefaultMutableTreeNode parent = (DefaultMutableTreeNode)treeNode.getParent(); fiore@3: if(parent == null) /* root node, just stay there */ fiore@3: nextTreeNode = treeNode; fiore@3: else /* loop = go to first child of own parent */ fiore@3: nextTreeNode = (DefaultMutableTreeNode)parent.getFirstChild(); fiore@3: loop = SoundEvent.LIST_BOTTOM_REACHED; fiore@3: } fiore@3: tree.setSelectionPath(new TreePath(nextTreeNode.getPath())); fiore@3: final String currentPathSpeech = currentPathSpeech(tree); fiore@3: SoundFactory.getInstance().play(loop, new PlayerListener(){ fiore@3: public void playEnded() { fiore@3: NarratorFactory.getInstance().speak(currentPathSpeech); fiore@3: } fiore@3: }); fiore@3: }}); fiore@3: fiore@3: tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP,0),"up"); fiore@3: tree.getActionMap().put("up", new AbstractAction(){ fiore@3: @Override fiore@3: public void actionPerformed(ActionEvent evt) { fiore@3: DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); fiore@3: DefaultMutableTreeNode previousTreeNode = treeNode.getPreviousSibling(); fiore@3: SoundEvent loop = null; fiore@3: if(previousTreeNode == null){ fiore@3: DefaultMutableTreeNode parent = (DefaultMutableTreeNode)treeNode.getParent(); fiore@3: if(parent == null) /* root node */ fiore@3: previousTreeNode = treeNode; fiore@3: else fiore@3: previousTreeNode = (DefaultMutableTreeNode)parent.getLastChild(); fiore@3: loop = SoundEvent.LIST_TOP_REACHED; fiore@3: } fiore@3: tree.setSelectionPath(new TreePath(previousTreeNode.getPath())); fiore@3: final String currentPathSpeech = currentPathSpeech(tree); fiore@3: SoundFactory.getInstance().play(loop, new PlayerListener(){ fiore@3: public void playEnded() { fiore@3: NarratorFactory.getInstance().speak(currentPathSpeech); fiore@3: } fiore@3: }); fiore@3: }}); fiore@3: fiore@3: tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0),"right"); fiore@3: tree.getActionMap().put("right", new AbstractAction(){ fiore@3: @Override fiore@3: public void actionPerformed(ActionEvent evt) { fiore@3: TreePath path = tree.getSelectionPath(); fiore@3: DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)path.getLastPathComponent(); fiore@3: if(treeNode.isLeaf()){ fiore@3: SoundFactory.getInstance().play(SoundEvent.ERROR); fiore@3: } fiore@3: else{ fiore@3: tree.expandPath(path); fiore@3: tree.setSelectionPath(new TreePath(((DefaultMutableTreeNode)treeNode.getFirstChild()).getPath())); fiore@3: final String currentPathSpeech = currentPathSpeech(tree); fiore@3: SoundFactory.getInstance().play(SoundEvent.TREE_NODE_EXPAND,new PlayerListener(){ fiore@3: @Override fiore@3: public void playEnded() { fiore@3: NarratorFactory.getInstance().speak(currentPathSpeech); fiore@3: } fiore@3: }); fiore@3: } fiore@3: } fiore@3: }); fiore@3: fiore@3: tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0),"left"); fiore@3: tree.getActionMap().put("left", new AbstractAction(){ fiore@3: @Override fiore@3: public void actionPerformed(ActionEvent evt) { fiore@3: TreePath path = tree.getSelectionPath(); fiore@3: DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)path.getLastPathComponent(); fiore@3: DefaultMutableTreeNode parent = (DefaultMutableTreeNode)treeNode.getParent(); fiore@3: if(parent == null){/* root node */ fiore@3: SoundFactory.getInstance().play(SoundEvent.ERROR); fiore@3: } fiore@3: else{ fiore@3: TreePath newPath = new TreePath(((DefaultMutableTreeNode)parent).getPath()); fiore@3: tree.setSelectionPath(newPath); fiore@3: tree.collapsePath(newPath); fiore@3: final String currentPathSpeech = currentPathSpeech(tree); fiore@3: SoundFactory.getInstance().play(SoundEvent.TREE_NODE_COLLAPSE,new PlayerListener(){ fiore@3: @Override fiore@3: public void playEnded() { fiore@3: NarratorFactory.getInstance().speak(currentPathSpeech); fiore@3: } fiore@3: }); fiore@3: } fiore@3: } fiore@3: }); fiore@3: fiore@3: tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0),"space"); fiore@3: tree.getActionMap().put("space",new AbstractAction(){ fiore@3: @Override fiore@3: public void actionPerformed(ActionEvent arg0) { fiore@3: space(tree); fiore@3: } fiore@3: }); fiore@3: /* make the tree ignore the page up and page down keys */ fiore@3: tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP,0),"none"); fiore@3: tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN,0),"none"); fiore@3: } fiore@3: fiore@3: protected String currentPathSpeech(JTree tree) { fiore@3: TreePath path = tree.getSelectionPath(); fiore@3: DefaultMutableTreeNode selectedPathTreeNode = (DefaultMutableTreeNode)path.getLastPathComponent(); fiore@3: return selectedPathTreeNode.toString(); fiore@3: } fiore@3: fiore@3: protected void space(JTree tree){ fiore@3: NarratorFactory.getInstance().speak(currentPathSpeech(tree)); fiore@3: } fiore@3: fiore@3: }