annotate java/src/uk/ac/qmul/eecs/ccmi/gui/SpeechMenuFactory.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;
f@0 21
f@0 22 import java.awt.event.ActionEvent;
f@0 23 import java.awt.event.ItemEvent;
f@0 24 import java.awt.event.ItemListener;
f@0 25 import java.awt.event.KeyEvent;
f@0 26 import java.awt.event.MouseEvent;
f@0 27 import java.text.MessageFormat;
f@0 28 import java.util.ResourceBundle;
f@0 29
f@0 30 import javax.swing.AbstractAction;
f@0 31 import javax.swing.Action;
f@0 32 import javax.swing.ComponentInputMap;
f@0 33 import javax.swing.JCheckBoxMenuItem;
f@0 34 import javax.swing.JComponent;
f@0 35 import javax.swing.JMenu;
f@0 36 import javax.swing.JMenuBar;
f@0 37 import javax.swing.JMenuItem;
f@0 38 import javax.swing.KeyStroke;
f@0 39 import javax.swing.MenuElement;
f@0 40 import javax.swing.MenuSelectionManager;
f@0 41
f@0 42 import uk.ac.qmul.eecs.ccmi.sound.SoundEvent;
f@0 43 import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
f@0 44 import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory;
f@0 45
f@0 46 /*
f@0 47 * This class provides a version of JMenuItem, JCheckBox, and JMenu which emit an "error" sound when
f@0 48 * they're disabled and the user tries to use it by an accelerator
f@0 49 */
f@0 50 @SuppressWarnings("serial")
f@0 51 class SpeechMenuFactory extends JMenu {
f@0 52
f@0 53 /* implements the singleton pattern and keeps a static reference to the menuBar used by JMenuItems and JMenus */
f@0 54 public static JMenuBar getMenuBar(){
f@0 55 if(menuBar == null){
f@0 56 menuBar = new SpeechMenuBar();
f@0 57 }
f@0 58 return menuBar;
f@0 59 }
f@0 60
f@0 61 public static JMenuItem getMenuItem(String text){
f@0 62 return new SpeechMenuItem(text);
f@0 63 }
f@0 64
f@0 65 public static JMenu getMenu(String text){
f@0 66 return new JMenu(text){
f@0 67 @Override
f@0 68 public void menuSelectionChanged(boolean isIncluded){
f@0 69 super.menuSelectionChanged(isIncluded);
f@0 70 if(isIncluded && !wasMouse){
f@0 71 String menuType = resources.getString("menufactory.menu");
f@0 72 if(getMenuBar().getComponentIndex(this) == -1){
f@0 73 menuType = resources.getString("menufactory.submenu");
f@0 74 };
f@0 75 NarratorFactory.getInstance().speak(getAccessibleContext().getAccessibleName()+ " "+ menuType);
f@0 76 }
f@0 77 wasMouse = false;
f@0 78 }
f@0 79
f@0 80 @Override
f@0 81 public void processMouseEvent(MouseEvent e){
f@0 82 wasMouse = true;
f@0 83 super.processMouseEvent(e);
f@0 84 }
f@0 85
f@0 86 private boolean wasMouse = false;
f@0 87 };
f@0 88 }
f@0 89
f@0 90 public static JCheckBoxMenuItem getJCheckBoxMenuItem(String text){
f@0 91 return new SpeechJCheckBoxMenuItem(text);
f@0 92 }
f@0 93
f@0 94 /* this action is called when the user strokes a disabled menu accelerator */
f@0 95 private static Action errorAction = new AbstractAction(){
f@0 96 @Override
f@0 97 public void actionPerformed(ActionEvent e) {
f@0 98 SoundFactory.getInstance().play(SoundEvent.ERROR);
f@0 99 }
f@0 100 };
f@0 101
f@0 102 private static class SpeechMenuBar extends JMenuBar{
f@0 103 SpeechMenuBar() {
f@0 104 setInputMap(SpeechMenuBar.WHEN_IN_FOCUSED_WINDOW, new ComponentInputMap(this){
f@0 105 @Override
f@0 106 public Object get(KeyStroke keyStroke){
f@0 107 if(keyStroke == null)
f@0 108 return null;
f@0 109 return super.get(keyStroke);
f@0 110 }
f@0 111 });
f@0 112 }
f@0 113
f@0 114 @Override
f@0 115 public void processKeyEvent(KeyEvent e, MenuElement[] path, MenuSelectionManager manager) {
f@0 116 super.processKeyEvent(e,path,manager);
f@0 117 if(e.getKeyCode() == KeyEvent.VK_ESCAPE){
f@0 118 NarratorFactory.getInstance().speak(resources.getString("menufactory.leaving"));
f@0 119 }
f@0 120 }
f@0 121 }
f@0 122
f@0 123 /*
f@0 124 * this class implements a menu item which speaks out its label when
f@0 125 * selected with the keyboard (mouse hover will have no effect)
f@0 126 * it needs a reference to the menu bar it's in to implement a respond, with the error sound, to
f@0 127 * the accelerator even when it's disabled (normally no listeners are called otherwise)
f@0 128 *
f@0 129 */
f@0 130 private static class SpeechMenuItem extends JMenuItem{
f@0 131 @Override
f@0 132 public void processMouseEvent(MouseEvent e ){
f@0 133 wasMouse = true;
f@0 134 super.processMouseEvent(e);
f@0 135 }
f@0 136
f@0 137 public SpeechMenuItem(String text){
f@0 138 super(text);
f@0 139 /* bind ACCELERATOR with the error action */
f@0 140 getMenuBar().getActionMap().put(ACCELERATOR, errorAction);
f@0 141 wasMouse = false;
f@0 142 if(text.trim().endsWith("...")){
f@0 143 /* replace the ... in the accessible name with the voice version of it */
f@0 144 String accName = getAccessibleContext().getAccessibleName().replaceAll("...\\s*$", "");
f@0 145 getAccessibleContext().setAccessibleName(accName +" "+ resources.getString("menufactory.3dot"));
f@0 146 }
f@0 147 }
f@0 148
f@0 149 @Override
f@0 150 public void menuSelectionChanged(boolean isIncluded){
f@0 151 super.menuSelectionChanged(isIncluded);
f@0 152 if(isIncluded && !wasMouse){
f@0 153 String disabled = isEnabled() ? "" : resources.getString("menufactory.disabled");
f@0 154 String accelerator = "";
f@0 155 if(getAccelerator() != null){
f@0 156 accelerator = resources.getString("menufactory.ctrl")+" "+ getAccelerator().toString().substring(getAccelerator().toString().lastIndexOf(' '));
f@0 157 }
f@0 158 NarratorFactory.getInstance().speak(getAccessibleContext().getAccessibleName()+disabled+accelerator);
f@0 159 }
f@0 160 wasMouse = false;
f@0 161 }
f@0 162
f@0 163 @Override
f@0 164 public void setEnabled(boolean b){
f@0 165 super.setEnabled(b);
f@0 166 if(getAccelerator() == null)
f@0 167 return;
f@0 168 if(b == false){
f@0 169 /* if the menu item gets disabled, then set up an action in the menuBar to respond to
f@0 170 * the accelerator key stroke, so that the user gets a feedback (error sound)
f@0 171 * even though the listeners don't get called (as the menu item is disabled)
f@0 172 */
f@0 173 getMenuBar().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(getAccelerator(), ACCELERATOR);
f@0 174 }else{
f@0 175 getMenuBar().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(getAccelerator(), "none");
f@0 176 }
f@0 177 }
f@0 178
f@0 179 private boolean wasMouse;
f@0 180 };
f@0 181
f@0 182 private static class SpeechJCheckBoxMenuItem extends JCheckBoxMenuItem {
f@0 183 public SpeechJCheckBoxMenuItem(String text){
f@0 184 super(text);
f@0 185 addItemListener(new ItemListener(){
f@0 186 @Override
f@0 187 public void itemStateChanged(ItemEvent evt) {
f@0 188 int stateChange = evt.getStateChange();
f@0 189 if(stateChange != ItemEvent.SELECTED && stateChange != ItemEvent.DESELECTED){
f@0 190 return;
f@0 191 }
f@0 192 if(!itemChangeMouseFlag){
f@0 193 NarratorFactory.getInstance().speak(
f@0 194 MessageFormat.format(
f@0 195 resources.getString(stateChange == ItemEvent.SELECTED ? "menufactory.selected" : "menufactory.unselected"),
f@0 196 getAccessibleContext().getAccessibleName()));
f@0 197 }
f@0 198 itemChangeMouseFlag = false;
f@0 199 }
f@0 200 });
f@0 201 }
f@0 202
f@0 203 @Override
f@0 204 public void menuSelectionChanged(boolean isIncluded){
f@0 205 super.menuSelectionChanged(isIncluded);
f@0 206 if(isIncluded && !selectionMouseFlag ){
f@0 207 NarratorFactory.getInstance().speak(
f@0 208 MessageFormat.format(
f@0 209 resources.getString(isSelected() ? "menufactory.selected" : "menufactory.unselected"),
f@0 210 getAccessibleContext().getAccessibleName()));
f@0 211 }
f@0 212 selectionMouseFlag = false;
f@0 213 }
f@0 214
f@0 215 @Override
f@0 216 public void processMouseEvent(MouseEvent e){
f@0 217 selectionMouseFlag = true;
f@0 218 itemChangeMouseFlag = true;
f@0 219 super.processMouseEvent(e);
f@0 220 }
f@0 221
f@0 222 private boolean selectionMouseFlag = false;
f@0 223 private boolean itemChangeMouseFlag = false;
f@0 224 }
f@0 225
f@0 226 private static JMenuBar menuBar;
f@0 227 private static ResourceBundle resources = ResourceBundle.getBundle(EditorFrame.class.getName());
f@0 228 private static final String ACCELERATOR = "accelerator";
f@0 229 }