KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > awt > Mnemonics


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  *
19  * Contributors: Maxym Mykhalchuk
20  */

21 package org.openide.awt;
22
23 import org.openide.util.Utilities;
24 import java.util.MissingResourceException JavaDoc;
25 import java.util.ResourceBundle JavaDoc;
26 import java.util.logging.Logger JavaDoc;
27 import javax.swing.AbstractButton JavaDoc;
28 import javax.swing.JLabel JavaDoc;
29
30
31 /**
32  * Support class for setting button, menu, and label text strings with mnemonics.
33  * @author Maxym Mykhalchuk
34  * @since 3.37
35  * @see <a HREF="http://www.netbeans.org/issues/show_bug.cgi?id=26640">Issue #26640</a>
36  */

37 public final class Mnemonics extends Object JavaDoc {
38     /** Private constructor in order that this class is never instantiated. */
39     private Mnemonics() {
40     }
41
42     /**
43      * Actual setter of the text & mnemonics for the AbstractButton/JLabel or
44      * their subclasses.
45      * @param item AbstractButton/JLabel
46      * @param text new label
47      */

48     private static void setLocalizedText2(Object JavaDoc item, String JavaDoc text) {
49         // #17664. Handle null text also.
50
// & in HTML should be ignored
51
if (text == null) { // NOI18N
52
setText(item, null);
53
54             return;
55         }
56
57         int i = findMnemonicAmpersand(text);
58
59         if (i < 0) {
60             // no '&' - don't set the mnemonic
61
setText(item, text);
62             setMnemonic(item, 0);
63         } else {
64             setText(item, text.substring(0, i) + text.substring(i + 1));
65             //#67807 no mnemonics on macosx
66
if (Utilities.isMac()) {
67                 setMnemonic(item, 0);
68             } else {
69                 char ch = text.charAt(i + 1);
70                 if (text.startsWith("<html>")) { // NOI18N
71
// Workaround for JDK bug #6510775
72
setText(item, text.substring(0, i) + "<u>" + ch + "</u>" + text.substring(i + 2)); // NOI18N
73
i += 3; // just in case it gets fixed
74
}
75                 if (((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z')) || ((ch >= '0') && (ch <= '9'))) {
76                     // it's latin character or arabic digit,
77
// setting it as mnemonics
78
setMnemonic(item, ch);
79                     
80                     // If it's something like "Save &As", we need to set another
81
// mnemonic index (at least under 1.4 or later)
82
// see #29676
83
setMnemonicIndex(item, i);
84                 } else {
85                     // it's non-latin, getting the latin correspondance
86
try {
87                         int latinCode = getLatinKeycode(ch);
88                         setMnemonic(item, latinCode);
89                         setMnemonicIndex(item, i);
90                     } catch (MissingResourceException JavaDoc e) {
91                         Logger.getLogger(Mnemonics.class.getName()).info("Mapping from a non-Latin character '"+ch+
92                                 "' not found in a localized (branded) version of "+
93                                 "openide/awt/src/org/openide/awt/Mnemonics.properties - "+
94                                 "mnemonic cannot be assigned in "+text);
95                     }
96                 }
97             }
98         }
99     }
100
101     /**
102      * Sets the text for a menu item or other subclass of AbstractButton.
103      * <p>Examples:</p>
104      * <table cellspacing="2" cellpadding="3" border="1">
105      * <tr><th>Input String</th> <th>View under JDK 1.4 or later</th></tr>
106      * <tr><td><code>Save &amp;As<code></td> <td>Save <u>A</u>s</td></tr>
107      * <tr><td><code>Rock &amp; Roll<code></td> <td>Rock &amp; Roll</td></tr>
108      * <tr><td><code>Drag &amp; &amp;Drop<code></td> <td>Drag &amp; <u>D</u>rop</td></tr>
109      * <tr><td><code>&amp;&#1060;&#1072;&#1081;&#1083;</code></td> <td><u>&#1060;</u>&#1072;&#1081;&#1083;</td></tr>
110      * </table>
111      * @param item a button whose text will be changed
112      * @param text new label
113      */

114     public static void setLocalizedText(AbstractButton JavaDoc item, String JavaDoc text) {
115         setLocalizedText2(item, text);
116     }
117
118     /**
119      * Sets the text for the label or other subclass of JLabel.
120      * For details see {@link #setLocalizedText(AbstractButton, String)}.
121      * @param item a label whose text will be set
122      * @param text new label
123      */

124     public static void setLocalizedText(JLabel JavaDoc item, String JavaDoc text) {
125         setLocalizedText2(item, text);
126     }
127
128     /**
129      * Searches for an ampersand in a string which indicates a mnemonic.
130      * Recognizes the following cases:
131      * <ul>
132      * <li>"Drag & Drop", "Ampersand ('&')" - don't have mnemonic ampersand.
133      * "&" is not found before " " (space), or if enclosed in "'"
134      * (single quotation marks).
135      * <li>"&File", "Save &As..." - do have mnemonic ampersand.
136      * <li>"Rock & Ro&ll", "Underline the '&' &character" - also do have
137      * mnemonic ampersand, but the second one.
138      * <li>"&lt;html&gt;&lt;b&gt;R&amp;amp;D&lt;/b&gt; departmen&amp;t" - has mnemonic
139      * ampersand before "t".
140      * Ampersands in HTML texts that are part of entity are ignored.
141      * </ul>
142      * @param text text to search
143      * @return the position of mnemonic ampersand in text, or -1 if there is none
144      */

145     public static int findMnemonicAmpersand(String JavaDoc text) {
146         int i = -1;
147         boolean isHTML = text.startsWith("<html>");
148
149         do {
150             // searching for the next ampersand
151
i = text.indexOf('&', i + 1);
152
153             if ((i >= 0) && ((i + 1) < text.length())) {
154                 if (isHTML) {
155                     boolean startsEntity = false;
156                     for (int j = i + 1; j < text.length(); j++) {
157                         char c = text.charAt(j);
158                         if (c == ';') {
159                             startsEntity = true;
160                             break;
161                         }
162                         if (!Character.isLetterOrDigit(c)) {
163                             break;
164                         }
165                     }
166                     if (!startsEntity) {
167                         return i;
168                     }
169                 }
170                 else {
171                     // before ' '
172
if (text.charAt(i + 1) == ' ') {
173                         continue;
174
175                         // before ', and after '
176
} else if ((text.charAt(i + 1) == '\'') && (i > 0) && (text.charAt(i - 1) == '\'')) {
177                         continue;
178                     }
179
180                     // ampersand is marking mnemonics
181
return i;
182                 }
183             }
184         } while (i >= 0);
185
186         return -1;
187     }
188
189     /**
190      * Gets the Latin symbol which corresponds
191      * to some non-Latin symbol on the localized keyboard.
192      * The search is done via lookup of Resource bundle
193      * for pairs having the form (e.g.) <code>MNEMONIC_?=A</code>.
194      * @param localeChar non-Latin character or a punctuator to be used as mnemonic
195      * @return character on latin keyboard, corresponding to the locale character,
196      * or the appropriate VK_*** code (if there's no latin character
197      * "under" the non-Latin one
198      */

199     private static int getLatinKeycode(char localeChar) throws MissingResourceException JavaDoc {
200         // associated should be a latin character, arabic digit
201
// or an integer (KeyEvent.VK_***)
202
String JavaDoc str = getBundle().getString("MNEMONIC_" + localeChar); // NOI18N
203

204         if (str.length() == 1) {
205             return str.charAt(0);
206         } else {
207             return Integer.parseInt(str);
208         }
209     }
210
211     /**
212      * Wrapper for the
213      * <code>AbstractButton.setMnemonicIndex</code> or
214      * <code>JLabel.setDisplayedMnemonicIndex</code> method.
215      * @param item AbstractButton/JLabel or subclasses
216      * @param index Index of the Character to underline under JDK1.4
217      * @param latinCode Latin Character Keycode to underline under JDK1.3
218      */

219     private static void setMnemonicIndex(Object JavaDoc item, int index) {
220         if (item instanceof AbstractButton JavaDoc) {
221             ((AbstractButton JavaDoc) item).setDisplayedMnemonicIndex(index);
222         } else if (item instanceof JLabel JavaDoc) {
223             ((JLabel JavaDoc) item).setDisplayedMnemonicIndex(index);
224         }
225     }
226
227     /**
228      * Wrapper for AbstractButton/JLabel.setText
229      * @param item AbstractButton/JLabel
230      * @param text the text to set
231      */

232     private static void setText(Object JavaDoc item, String JavaDoc text) {
233         if (item instanceof AbstractButton JavaDoc) {
234             ((AbstractButton JavaDoc) item).setText(text);
235         } else {
236             ((JLabel JavaDoc) item).setText(text);
237         }
238     }
239
240     /**
241      * Wrapper for AbstractButton.setMnemonic and JLabel.setDisplayedMnemonic
242      * @param item AbstractButton/JLabel
243      * @param mnem Mnemonic char to set, latin [a-z,A-Z], digit [0-9], or any VK_ code
244      */

245     private static void setMnemonic(Object JavaDoc item, int mnem) {
246         if (Utilities.isMac()) {
247             // there shall be no mnemonics on macosx.
248
//#55864
249
return;
250         }
251
252         if ((mnem >= 'a') && (mnem <= 'z')) {
253             mnem = mnem + ('A' - 'a');
254         }
255
256         if (item instanceof AbstractButton JavaDoc) {
257             ((AbstractButton JavaDoc) item).setMnemonic(mnem);
258         } else {
259             ((JLabel JavaDoc) item).setDisplayedMnemonic(mnem);
260         }
261     }
262
263     /**
264      * Getter for the used Resource bundle (org.openide.awt.Mnemonics).
265      * Used to avoid calling </code>ResourceBundle.getBundle(...)</code>
266      * many times in defferent places of the code.
267      * Does no caching, it's simply an utility method.
268      */

269     private static ResourceBundle JavaDoc getBundle() {
270         return ResourceBundle.getBundle("org.openide.awt.Mnemonics"); // NOI18N
271
}
272 }
273
Popular Tags