annotate java/src/uk/ac/qmul/eecs/ccmi/gui/filechooser/FileSystemTree.java @ 1:e3935c01cde2 tip

moved license of PdPersistenceManager to the beginning of the file
author Fiore Martin <f.martin@qmul.ac.uk>
date Tue, 08 Jul 2014 19:52:03 +0100
parents 78b7fc5391a2
children
rev   line source
f@0 1 /*
f@0 2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
f@0 3
f@0 4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
f@0 5
f@0 6 This program is free software: you can redistribute it and/or modify
f@0 7 it under the terms of the GNU General Public License as published by
f@0 8 the Free Software Foundation, either version 3 of the License, or
f@0 9 (at your option) any later version.
f@0 10
f@0 11 This program is distributed in the hope that it will be useful,
f@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@0 14 GNU General Public License for more details.
f@0 15
f@0 16 You should have received a copy of the GNU General Public License
f@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@0 18 */
f@0 19
f@0 20 package uk.ac.qmul.eecs.ccmi.gui.filechooser;
f@0 21
f@0 22 import java.awt.Component;
f@0 23 import java.awt.event.ActionEvent;
f@0 24 import java.awt.event.InputEvent;
f@0 25 import java.awt.event.KeyEvent;
f@0 26 import java.awt.event.MouseEvent;
f@0 27 import java.io.File;
f@0 28 import java.io.IOException;
f@0 29 import java.util.LinkedList;
f@0 30 import java.util.ResourceBundle;
f@0 31
f@0 32 import javax.swing.AbstractAction;
f@0 33 import javax.swing.JTree;
f@0 34 import javax.swing.KeyStroke;
f@0 35 import javax.swing.event.TreeSelectionEvent;
f@0 36 import javax.swing.event.TreeSelectionListener;
f@0 37 import javax.swing.filechooser.FileFilter;
f@0 38 import javax.swing.tree.DefaultTreeModel;
f@0 39 import javax.swing.tree.TreeCellRenderer;
f@0 40 import javax.swing.tree.TreeNode;
f@0 41 import javax.swing.tree.TreePath;
f@0 42 import javax.swing.tree.TreeSelectionModel;
f@0 43
f@0 44 import uk.ac.qmul.eecs.ccmi.sound.PlayerListener;
f@0 45 import uk.ac.qmul.eecs.ccmi.sound.SoundEvent;
f@0 46 import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
f@0 47 import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory;
f@0 48
f@0 49 /*
f@0 50 *
f@0 51 * A JTree displaying the content for the local file system.
f@0 52 *
f@0 53 *
f@0 54 */
f@0 55 @SuppressWarnings("serial")
f@0 56 class FileSystemTree extends JTree {
f@0 57 FileSystemTree(FileFilter filter){
f@0 58 super(new DefaultTreeModel(FileSystemTreeNode.getRootNode(filter)));
f@0 59 getAccessibleContext().setAccessibleName(ResourceBundle.getBundle(SpeechFileChooser.class.getName()).getString("tree.accessible_name"));
f@0 60 getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
f@0 61 setCellRenderer(new FileSystemTreeCellRendered(getCellRenderer()));
f@0 62
f@0 63 setSelectionPath(new TreePath(getModel().getRoot()));
f@0 64 overwriteTreeKeystrokes();
f@0 65 this.addTreeSelectionListener(new TreeSelectionListener(){
f@0 66 @Override
f@0 67 public void valueChanged(TreeSelectionEvent evt) {
f@0 68 if(treeSelectionListenerGateOpen){
f@0 69 FileSystemTreeNode treeNode = (FileSystemTreeNode)evt.getPath().getLastPathComponent();
f@0 70 NarratorFactory.getInstance().speak(treeNode.spokenText());
f@0 71 }
f@0 72 }
f@0 73 });
f@0 74 }
f@0 75
f@0 76 @Override
f@0 77 public void setSelectionPath(TreePath path){
f@0 78 super.setSelectionPath(path);
f@0 79 scrollPathToVisible(path);
f@0 80 getSelectionPath();
f@0 81 }
f@0 82
f@0 83 public void setSelectionPath(File file){
f@0 84 if(file == null)
f@0 85 return;
f@0 86
f@0 87 try {
f@0 88 file = file.getCanonicalFile();
f@0 89 } catch (IOException e) {
f@0 90 setSelectionPath(new TreePath(getModel().getRoot()));
f@0 91 return;
f@0 92 }
f@0 93 /* make a file path: a list of file's each one representing a directory of file's path */
f@0 94 LinkedList<File> filePath = new LinkedList<File>();
f@0 95 filePath.add(file);
f@0 96 File parent = file.getParentFile();
f@0 97 while(parent != null){
f@0 98 filePath.add(0, parent);
f@0 99 parent = parent.getParentFile();
f@0 100 }
f@0 101 /* make a TreePath out of the file path */
f@0 102 FileSystemTreeNode currentNode = (FileSystemTreeNode)getModel().getRoot();
f@0 103 TreePath treePath = new TreePath(currentNode);
f@0 104 for(File f : filePath){
f@0 105 boolean found = false;
f@0 106 for(int i=0;i<currentNode.getChildCount();i++){
f@0 107 if(currentNode.getChildAt(i).getFile().equals(f)){
f@0 108 currentNode = currentNode.getChildAt(i);
f@0 109 treePath = treePath.pathByAddingChild(currentNode);
f@0 110 found = true;
f@0 111 break;
f@0 112 }
f@0 113 }
f@0 114 if(!found)
f@0 115 break;
f@0 116 }
f@0 117 treeSelectionListenerGateOpen = false;
f@0 118 setSelectionPath(treePath);
f@0 119 treeSelectionListenerGateOpen = true;
f@0 120 }
f@0 121
f@0 122 public void applyFilter(FileFilter filter){
f@0 123 FileSystemTreeNode selectedNode = (FileSystemTreeNode)getSelectionPath().getLastPathComponent();
f@0 124 File file = selectedNode.getFile();
f@0 125 treeSelectionListenerGateOpen = false;
f@0 126 ((DefaultTreeModel)getModel()).setRoot(FileSystemTreeNode.getRootNode(filter));
f@0 127 treeSelectionListenerGateOpen = true;
f@0 128 if(file == null)
f@0 129 setSelectionPath(new TreePath(getModel().getRoot()));
f@0 130 else
f@0 131 setSelectionPath(file);
f@0 132 }
f@0 133
f@0 134 @Override
f@0 135 protected void processMouseEvent(MouseEvent e){
f@0 136 //do nothing as the tree does not have to be editable with mouse
f@0 137 }
f@0 138
f@0 139 private void overwriteTreeKeystrokes() {
f@0 140 /* overwrite the keys. up and down arrow are overwritten so that it loops when the top and the */
f@0 141 /* bottom are reached rather than getting stuck */
f@0 142
f@0 143 /* Overwrite keystrokes up,down,left,right arrows and space, shift, ctrl */
f@0 144 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0),"down");
f@0 145 getActionMap().put("down", new AbstractAction(){
f@0 146 @Override
f@0 147 public void actionPerformed(ActionEvent evt) {
f@0 148 FileSystemTreeNode treeNode = (FileSystemTreeNode)getLastSelectedPathComponent();
f@0 149 /* look if we've got a sibling node after (we are not at the bottom) */
f@0 150 FileSystemTreeNode nextTreeNode = treeNode.getNextSibling();
f@0 151 SoundEvent loop = null;
f@0 152 if(nextTreeNode == null){
f@0 153 TreeNode parent = treeNode.getParent();
f@0 154 if(parent == null) /* root node, just stay there */
f@0 155 nextTreeNode = treeNode;
f@0 156 else /* loop = go to first child of own parent */
f@0 157 nextTreeNode = (FileSystemTreeNode)parent.getChildAt(0);
f@0 158 loop = SoundEvent.LIST_BOTTOM_REACHED;
f@0 159 }
f@0 160
f@0 161 final String speech = nextTreeNode.spokenText();
f@0 162 treeSelectionListenerGateOpen = false;
f@0 163 setSelectionPath(new TreePath(nextTreeNode.getPath()));
f@0 164 treeSelectionListenerGateOpen = true;
f@0 165 SoundFactory.getInstance().play(loop, new PlayerListener(){
f@0 166 public void playEnded() {
f@0 167 NarratorFactory.getInstance().speak(speech);
f@0 168 }
f@0 169 });
f@0 170 }});
f@0 171
f@0 172 /* Overwrite keystrokes up,down,left,right arrows and space, shift, ctrl */
f@0 173 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP,0),"up");
f@0 174 getActionMap().put("up", new AbstractAction(){
f@0 175 @Override
f@0 176 public void actionPerformed(ActionEvent evt) {
f@0 177 FileSystemTreeNode treeNode = (FileSystemTreeNode)getLastSelectedPathComponent();
f@0 178 /* look if we've got a sibling node after (we are not at the bottom) */
f@0 179 FileSystemTreeNode peviousTreeNode = treeNode.getPreviousSibling();
f@0 180 SoundEvent loop = null;
f@0 181 if(peviousTreeNode == null){
f@0 182 TreeNode parent = treeNode.getParent();
f@0 183 if(parent == null) /* root node, just stay there */
f@0 184 peviousTreeNode = treeNode;
f@0 185 else /* loop = go to first child of own parent */
f@0 186 peviousTreeNode = (FileSystemTreeNode)parent.getChildAt(parent.getChildCount()-1);
f@0 187 loop = SoundEvent.LIST_TOP_REACHED;
f@0 188 }
f@0 189
f@0 190 final String speech = peviousTreeNode.spokenText();
f@0 191 treeSelectionListenerGateOpen = false;
f@0 192 setSelectionPath(new TreePath(peviousTreeNode.getPath()));
f@0 193 treeSelectionListenerGateOpen = true;
f@0 194 SoundFactory.getInstance().play(loop, new PlayerListener(){
f@0 195 public void playEnded() {
f@0 196 NarratorFactory.getInstance().speak(speech);
f@0 197 }
f@0 198 });
f@0 199 }});
f@0 200
f@0 201 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0),"left");
f@0 202 getActionMap().put("left", new AbstractAction(){
f@0 203 @Override
f@0 204 public void actionPerformed(ActionEvent evt) {
f@0 205 TreePath path = getSelectionPath();
f@0 206 TreeNode treeNode = (TreeNode)path.getLastPathComponent();
f@0 207 final FileSystemTreeNode parent = (FileSystemTreeNode)treeNode.getParent();
f@0 208 if(parent == null){/* root node */
f@0 209 SoundFactory.getInstance().play(SoundEvent.ERROR);
f@0 210 }
f@0 211 else{
f@0 212 TreePath newPath = new TreePath(parent.getPath());
f@0 213 treeSelectionListenerGateOpen = false;
f@0 214 setSelectionPath(newPath);
f@0 215 collapsePath(newPath);
f@0 216 treeSelectionListenerGateOpen = true;
f@0 217 SoundFactory.getInstance().play(SoundEvent.TREE_NODE_COLLAPSE,new PlayerListener(){
f@0 218 @Override
f@0 219 public void playEnded() {
f@0 220 NarratorFactory.getInstance().speak(parent.spokenText());
f@0 221 }
f@0 222 });
f@0 223 }
f@0 224 }
f@0 225 });
f@0 226
f@0 227 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0),"right");
f@0 228 getActionMap().put("right", new AbstractAction(){
f@0 229 @Override
f@0 230 public void actionPerformed(ActionEvent evt) {
f@0 231 TreePath path = getSelectionPath();
f@0 232 TreeNode treeNode = (TreeNode)path.getLastPathComponent();
f@0 233 if(treeNode.isLeaf()){/* leaf node */
f@0 234 SoundFactory.getInstance().play(SoundEvent.ERROR);
f@0 235 }
f@0 236 else{
f@0 237 expandPath(path);
f@0 238 final FileSystemTreeNode firstChild = (FileSystemTreeNode)treeNode.getChildAt(0);
f@0 239 treeSelectionListenerGateOpen = false;
f@0 240 setSelectionPath(new TreePath(firstChild.getPath()));
f@0 241 treeSelectionListenerGateOpen = true;
f@0 242 SoundFactory.getInstance().play(SoundEvent.TREE_NODE_EXPAND,new PlayerListener(){
f@0 243 @Override
f@0 244 public void playEnded() {
f@0 245 NarratorFactory.getInstance().speak(firstChild.spokenText());
f@0 246 }
f@0 247 });
f@0 248 }
f@0 249 }
f@0 250 });
f@0 251
f@0 252 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0),"space");
f@0 253 getActionMap().put("space",new AbstractAction(){
f@0 254 @Override
f@0 255 public void actionPerformed(ActionEvent evt) {
f@0 256 TreePath path = getSelectionPath();
f@0 257 FileSystemTreeNode treeNode = (FileSystemTreeNode)path.getLastPathComponent();
f@0 258 NarratorFactory.getInstance().speak(treeNode.toString());
f@0 259 }
f@0 260 });
f@0 261
f@0 262 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,InputEvent.CTRL_DOWN_MASK), "ctrl_space");
f@0 263 getActionMap().put("ctrl_space", new AbstractAction(){
f@0 264 @Override
f@0 265 public void actionPerformed(ActionEvent evt) {
f@0 266 TreePath path = getSelectionPath();
f@0 267 FileSystemTreeNode treeNode = (FileSystemTreeNode)path.getLastPathComponent();
f@0 268 NarratorFactory.getInstance().speak(treeNode.getFile().getPath());
f@0 269 }
f@0 270 });
f@0 271 /* make the tree ignore the page up and page down keys */
f@0 272 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP,0),"none");
f@0 273 getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN,0),"none");
f@0 274 }
f@0 275 private boolean treeSelectionListenerGateOpen;
f@0 276 }
f@0 277
f@0 278 /**
f@0 279 * This class overwrites the default cell renderer in order to always render directories with a
f@0 280 * directory-icon regardless whether they are a leaf node or not.
f@0 281 *
f@0 282 */
f@0 283 class FileSystemTreeCellRendered implements TreeCellRenderer {
f@0 284 FileSystemTreeCellRendered(TreeCellRenderer delegate){
f@0 285 this.delegate = delegate;
f@0 286 }
f@0 287
f@0 288 @Override
f@0 289 public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected,
f@0 290 boolean expanded, boolean leaf, int row, boolean hasFocus) {
f@0 291 if(leaf && ((FileSystemTreeNode)value).getFile().isDirectory() )
f@0 292 return delegate.getTreeCellRendererComponent(tree, value, selected, expanded, false, row, hasFocus);
f@0 293 return delegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
f@0 294 }
f@0 295
f@0 296 TreeCellRenderer delegate;
f@0 297 }