1 /* 2 * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.im; 27 28 import java.awt.AWTException; 29 import java.awt.CheckboxMenuItem; 30 import java.awt.Component; 31 import java.awt.Container; 32 import java.awt.PopupMenu; 33 import java.awt.Menu; 34 import java.awt.MenuItem; 35 import java.awt.Toolkit; 36 import java.awt.event.ActionEvent; 37 import java.awt.event.ActionListener; 38 import java.awt.im.spi.InputMethodDescriptor; 39 import java.util.Locale; 40 import javax.swing.JCheckBoxMenuItem; 41 import javax.swing.JComponent; 42 import javax.swing.JDialog; 43 import javax.swing.JFrame; 44 import javax.swing.JPopupMenu; 45 import javax.swing.JMenu; 46 import javax.swing.JMenuItem; 47 48 /** 49 * {@code InputMethodPopupMenu} provides the popup selection menu 50 */ 51 52 abstract class InputMethodPopupMenu implements ActionListener { 53 54 // Factory method to provide the menu, depending on the client, i.e., 55 // provide Swing popup menu if client is a swing app, otherwise AWT popup 56 // is created. getInstance(Component client, String title)57 static InputMethodPopupMenu getInstance(Component client, String title) { 58 if ((client instanceof JFrame) || 59 (client instanceof JDialog)) { 60 return new JInputMethodPopupMenu(title); 61 } else { 62 return new AWTInputMethodPopupMenu(title); 63 } 64 } 65 show(Component c, int x, int y)66 abstract void show(Component c, int x, int y); 67 removeAll()68 abstract void removeAll(); 69 addSeparator()70 abstract void addSeparator(); 71 addToComponent(Component c)72 abstract void addToComponent(Component c); 73 createSubmenu(String label)74 abstract Object createSubmenu(String label); 75 add(Object menuItem)76 abstract void add(Object menuItem); 77 addMenuItem(String label, String command, String currentSelection)78 abstract void addMenuItem(String label, String command, String currentSelection); 79 addMenuItem(Object targetMenu, String label, String command, String currentSelection)80 abstract void addMenuItem(Object targetMenu, String label, String command, 81 String currentSelection); 82 addOneInputMethodToMenu(InputMethodLocator locator, String currentSelection)83 void addOneInputMethodToMenu(InputMethodLocator locator, String currentSelection) { 84 InputMethodDescriptor descriptor = locator.getDescriptor(); 85 String label = descriptor.getInputMethodDisplayName(null, Locale.getDefault()); 86 String command = locator.getActionCommandString(); 87 Locale[] locales = null; 88 int localeCount; 89 try { 90 locales = descriptor.getAvailableLocales(); 91 localeCount = locales.length; 92 } catch (AWTException e) { 93 // ??? should have better error handling - 94 // tell user what happened, then remove this input method from the list. 95 // For the time being, just show it disabled. 96 localeCount = 0; 97 } 98 if (localeCount == 0) { 99 // could be IIIMP adapter which has lost its connection 100 addMenuItem(label, null, currentSelection); 101 } else if (localeCount == 1) { 102 if (descriptor.hasDynamicLocaleList()) { 103 // try to make sure that what the user sees and what 104 // we eventually select is consistent even if the locale 105 // list changes in the meantime 106 label = descriptor.getInputMethodDisplayName(locales[0], Locale.getDefault()); 107 command = locator.deriveLocator(locales[0]).getActionCommandString(); 108 } 109 addMenuItem(label, command, currentSelection); 110 } else { 111 Object submenu = createSubmenu(label); 112 add(submenu); 113 for (int j = 0; j < localeCount; j++) { 114 Locale locale = locales[j]; 115 String subLabel = getLocaleName(locale); 116 String subCommand = locator.deriveLocator(locale).getActionCommandString(); 117 addMenuItem(submenu, subLabel, subCommand, currentSelection); 118 } 119 } 120 } 121 122 /** 123 * Returns whether command indicates the same input method as currentSelection, 124 * taking into account that command may not specify a locale where currentSelection does. 125 */ isSelected(String command, String currentSelection)126 static boolean isSelected(String command, String currentSelection) { 127 if (command == null || currentSelection == null) { 128 return false; 129 } 130 if (command.equals(currentSelection)) { 131 return true; 132 } 133 // currentSelection may indicate a locale where command does not 134 int index = currentSelection.indexOf('\n'); 135 if (index != -1 && currentSelection.substring(0, index).equals(command)) { 136 return true; 137 } 138 return false; 139 } 140 141 /** 142 * Returns a localized locale name for input methods with the 143 * given locale. It falls back to Locale.getDisplayName() and 144 * then to Locale.toString() if no localized locale name is found. 145 * 146 * @param locale Locale for which localized locale name is obtained 147 */ getLocaleName(Locale locale)148 String getLocaleName(Locale locale) { 149 String localeString = locale.toString(); 150 String localeName = Toolkit.getProperty("AWT.InputMethodLanguage." + localeString, null); 151 if (localeName == null) { 152 localeName = locale.getDisplayName(); 153 if (localeName == null || localeName.length() == 0) 154 localeName = localeString; 155 } 156 return localeName; 157 } 158 159 // ActionListener implementation actionPerformed(ActionEvent event)160 public void actionPerformed(ActionEvent event) { 161 String choice = event.getActionCommand(); 162 ((ExecutableInputMethodManager)InputMethodManager.getInstance()).changeInputMethod(choice); 163 } 164 165 } 166 167 class JInputMethodPopupMenu extends InputMethodPopupMenu { 168 static JPopupMenu delegate = null; 169 JInputMethodPopupMenu(String title)170 JInputMethodPopupMenu(String title) { 171 synchronized (this) { 172 if (delegate == null) { 173 delegate = new JPopupMenu(title); 174 } 175 } 176 } 177 show(Component c, int x, int y)178 void show(Component c, int x, int y) { 179 delegate.show(c, x, y); 180 } 181 removeAll()182 void removeAll() { 183 delegate.removeAll(); 184 } 185 addSeparator()186 void addSeparator() { 187 delegate.addSeparator(); 188 } 189 addToComponent(Component c)190 void addToComponent(Component c) { 191 } 192 createSubmenu(String label)193 Object createSubmenu(String label) { 194 return new JMenu(label); 195 } 196 add(Object menuItem)197 void add(Object menuItem) { 198 delegate.add((JMenuItem)menuItem); 199 } 200 addMenuItem(String label, String command, String currentSelection)201 void addMenuItem(String label, String command, String currentSelection) { 202 addMenuItem(delegate, label, command, currentSelection); 203 } 204 addMenuItem(Object targetMenu, String label, String command, String currentSelection)205 void addMenuItem(Object targetMenu, String label, String command, String currentSelection) { 206 JMenuItem menuItem; 207 if (isSelected(command, currentSelection)) { 208 menuItem = new JCheckBoxMenuItem(label, true); 209 } else { 210 menuItem = new JMenuItem(label); 211 } 212 menuItem.setActionCommand(command); 213 menuItem.addActionListener(this); 214 menuItem.setEnabled(command != null); 215 if (targetMenu instanceof JMenu) { 216 ((JMenu)targetMenu).add(menuItem); 217 } else { 218 ((JPopupMenu)targetMenu).add(menuItem); 219 } 220 } 221 222 } 223 224 class AWTInputMethodPopupMenu extends InputMethodPopupMenu { 225 static PopupMenu delegate = null; 226 AWTInputMethodPopupMenu(String title)227 AWTInputMethodPopupMenu(String title) { 228 synchronized (this) { 229 if (delegate == null) { 230 delegate = new PopupMenu(title); 231 } 232 } 233 } 234 show(Component c, int x, int y)235 void show(Component c, int x, int y) { 236 delegate.show(c, x, y); 237 } 238 removeAll()239 void removeAll() { 240 delegate.removeAll(); 241 } 242 addSeparator()243 void addSeparator() { 244 delegate.addSeparator(); 245 } 246 addToComponent(Component c)247 void addToComponent(Component c) { 248 c.add(delegate); 249 } 250 createSubmenu(String label)251 Object createSubmenu(String label) { 252 return new Menu(label); 253 } 254 add(Object menuItem)255 void add(Object menuItem) { 256 delegate.add((MenuItem)menuItem); 257 } 258 addMenuItem(String label, String command, String currentSelection)259 void addMenuItem(String label, String command, String currentSelection) { 260 addMenuItem(delegate, label, command, currentSelection); 261 } 262 addMenuItem(Object targetMenu, String label, String command, String currentSelection)263 void addMenuItem(Object targetMenu, String label, String command, String currentSelection) { 264 MenuItem menuItem; 265 if (isSelected(command, currentSelection)) { 266 menuItem = new CheckboxMenuItem(label, true); 267 } else { 268 menuItem = new MenuItem(label); 269 } 270 menuItem.setActionCommand(command); 271 menuItem.addActionListener(this); 272 menuItem.setEnabled(command != null); 273 ((Menu)targetMenu).add(menuItem); 274 } 275 } 276