source: trunk/gli/src/org/greenstone/gatherer/Dictionary.java@ 8811

Last change on this file since 8811 was 8811, checked in by mdewsnip, 19 years ago

Minor tidy ups.

  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer;
38
39import java.awt.*;
40import java.io.*;
41import java.util.*;
42import javax.swing.*;
43import javax.swing.plaf.*;
44import javax.swing.text.*;
45import javax.swing.tree.*;
46import org.greenstone.gatherer.util.Utility;
47
48/** Extends the ResourceBundle class to allow for the automatic insertion of arguments. Note that the key names beginning Farg are reserved for formatting. <BR>
49 * <BR>
50 * Property files usable by this class have the Backus-Naur form: <BR>
51 * <BR>
52 * FileLine ::= Comment | Mapping <BR>
53 * Comment ::= '#' SString <BR>
54 * Mapping ::= NZString ':' SString ( Argument SString )* <BR>
55 * NZString ::= ( Char | Int ) SString <BR>
56 * Argument ::= '{' Int '}' <BR>
57 * SString ::= String . ['"','#',...] -> ['\"','\#',...] <BR>
58 * <BR>
59 * In order to add a new dictionary Locale, simply copy the existing dictionary.properties files, replace the values (Strings after the ':') with the new language specific ones being careful to maintain formatting and Gatherer placed arguments, then save the new dictionary as: <br>
60 * <BR>
61 * dictionary_<I>locale</I>.properties<BR>
62 * <BR>
63 * where locale is made of two two-letter codes seperated by an underscore. The first code is in lower-case and defines the language. The second is in upper-case and defines the country. For example the default dictionary could also correctly be called:
64 * <BR>
65 * dictionary_en_NZ.properties<BR>
66 * @author John Thompson, Greenstone Digital Library, University of Waikato
67 * @version 2.3
68 */
69public class Dictionary
70 extends HashMap {
71
72 /** The font used when displaying various html text. */
73 static private FontUIResource font = null;
74 /** A reference to remind us of the current locale. */
75 static private Locale locale = null;
76 /** The ResourceBundle which contains the raw key-value mappings.
77 Loaded from a file named "dictionary<I>locale</I>.properties. */
78 static private ResourceBundle dictionary = null;
79
80
81 public Dictionary(Locale locale, FontUIResource font)
82 {
83 super();
84
85 // Initialize
86 this.font = font;
87 this.locale = ((locale == null) ? Locale.getDefault() : locale);
88 this.dictionary = ResourceBundle.getBundle("dictionary", this.locale);
89 }
90
91
92 /** Retrieve the two letter code of the current language we are using, according to the stored locale.
93 * @return A <strong>String</strong> containing the two letter ISO639 language code.
94 */
95 static public String getLanguage()
96 {
97 return locale.getLanguage();
98 }
99
100
101 static public String get(String key)
102 {
103 return get(key, (String[]) null);
104 }
105
106
107 static public String get(String key, String arg)
108 {
109 String[] args = new String[1];
110 args[0] = arg;
111 return get(key, args);
112 }
113
114
115 /** Used to retrieve a property value from the Locale specific ResourceBundle, based upon the key and arguments supplied. If the key cannot be found or if some other part of the call fails a default (English) error message is returned. <BR>
116 * Here the get recieves a second argument which is an array of Strings used to populate argument fields, denoted {<I>n</I>}, within the value String returned. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>.
117 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle.
118 * @param args A <strong>String[]</strong> used to populate argument fields within the complete String.
119 * @return A <strong>String</strong> which has been referenced by the key String and that either contains no argument fields, or has had the argument fields automatiically populated with formatting Strings of with argument String provided in the get call.
120 */
121 static public String get(String key, String[] args)
122 {
123 try {
124 String initial_raw = dictionary.getString(key);
125
126 // Convert into Unicode
127 String initial = "";
128 try {
129 // This "ISO-8859-1" looks out of place, but it is very important.
130 // It is essential to call getBytes with an 8-bit encoding, otherwise
131 // Java kindly deems some characters "undisplayable", and replaces
132 // them with question marks. This is NOT good.
133 initial = new String(initial_raw.getBytes("ISO-8859-1"), "UTF-8");
134 }
135 catch (Exception ex) {
136 System.err.println("Exception: " + ex);
137 ex.printStackTrace();
138 return initial_raw;
139 }
140
141 // If the string contains arguments we have to insert them.
142 String complete = "";
143
144 // While we still have initial string left.
145 while(initial.length() > 0 && initial.indexOf('{') != -1 && initial.indexOf('}') != -1) {
146 // Remove preamble
147 int opening = initial.indexOf('{');
148 int closing = initial.indexOf('}');
149 int comment_mark = initial.indexOf('-', opening); // May not exist
150 if (comment_mark > closing) { // May also be detecting a later comment
151 comment_mark = -1;
152 }
153 complete = complete + initial.substring(0, opening);
154 // Parse arg_num
155 String arg_str = null;
156 if (comment_mark != -1) {
157 arg_str = initial.substring(opening + 1, comment_mark);
158 }
159 else {
160 arg_str = initial.substring(opening + 1, closing);
161 }
162 int arg_num = Integer.parseInt(arg_str);
163 if (closing + 1 < initial.length()) {
164 initial = initial.substring(closing + 1);
165 }
166 else {
167 initial = "";
168 }
169 // Insert argument
170 if (args != null && 0 <= arg_num && arg_num < args.length) {
171 complete = complete + args[arg_num];
172 }
173 else if (arg_num >= 32) {
174 String f_subargs[] = new String[1];
175 if (font != null) {
176 f_subargs[0] = font.getFontName();
177 }
178 else {
179 f_subargs[0] = "Arial";
180 }
181 complete = complete + get("Farg" + arg_num, f_subargs);
182 }
183 }
184 complete = complete + initial;
185
186 return complete;
187 }
188 catch (Exception e) {
189 System.err.println("Missing value for key: " + key);
190 // DebugStream.printStackTrace(e);
191 return key;
192 }
193 }
194
195
196 static public void registerBoth(Component component, String text_key, String tooltip_key)
197 {
198 setText(component, text_key);
199 setTooltip(component, tooltip_key);
200 }
201
202
203 static public void registerText(Component component, String text_key)
204 {
205 setText(component, text_key);
206 }
207
208
209 static public void registerText(Component component, String text_key, String[] args)
210 {
211 setText(component, text_key, args);
212 }
213
214
215 static public void registerTooltip(Component component, String tooltip_key)
216 {
217 setTooltip(component, tooltip_key);
218 }
219
220
221 static public void registerTooltipText(Component component, String tooltip)
222 {
223 setTooltipText(component, tooltip);
224 }
225
226
227 static public void setBoth(Component component, String text_key, String tooltip_key)
228 {
229 setText(component, text_key);
230 setTooltip(component, tooltip_key);
231 }
232
233
234 static public void setText(Component component, String text_key)
235 {
236 setText(component, text_key, null);
237 }
238
239
240 static public void setText(Component component, String text_key, String[] args)
241 {
242 if (component != null) {
243 // Update the component using the AWTEvent queue
244 SwingUtilities.invokeLater(new ComponentUpdateTask(component, get(text_key, args), null));
245 }
246 }
247
248
249 static public void setTooltip(Component component, String tooltip_key)
250 {
251 if (component != null) {
252 // Update the component using the AWTEvent queue
253 SwingUtilities.invokeLater(new ComponentUpdateTask(component, null, get(tooltip_key)));
254 }
255 }
256
257
258 static public void setTooltipText(Component component, String tooltip)
259 {
260 if (component != null) {
261 // Update the component using the AWTEvent queue
262 SwingUtilities.invokeLater(new ComponentUpdateTask(component, null, tooltip));
263 }
264 }
265
266
267 static private class ComponentUpdateTask
268 implements Runnable {
269
270 private Component component = null;
271 private String text = null;
272 private String tooltip = null;
273
274
275 public ComponentUpdateTask(Component component, String text, String tooltip)
276 {
277 this.component = component;
278 this.text = text;
279 this.tooltip = tooltip;
280 }
281
282
283 public void run()
284 {
285 // If the component has text
286 if (text != null) {
287 if (component instanceof AbstractButton) {
288 ((AbstractButton) component).setText(text);
289 }
290 else if (component instanceof Frame) {
291 ((Frame) component).setTitle(text);
292 }
293 else if (component instanceof JDialog) {
294 ((JDialog) component).setTitle(text);
295 }
296 else if (component instanceof JLabel) {
297 ((JLabel) component).setText(text);
298 }
299 else if (component instanceof JProgressBar) {
300 ((JProgressBar) component).setString(text);
301 }
302 else if (component instanceof JTextComponent) {
303 ((JTextComponent) component).setText(text);
304 ((JTextComponent) component).setCaretPosition(0);
305 }
306 else {
307 System.err.println("Unhandled component: " + component.getClass());
308 }
309 }
310
311 // If the component has a tooltip
312 if (tooltip != null) {
313 if (component instanceof JComponent) {
314 ((JComponent) component).setToolTipText(tooltip);
315 }
316 }
317 }
318 }
319
320
321 /**
322 * Register a tab pane component. This will be deprecated eventually. */
323 static public void register(JTabbedPane component)
324 {
325 if (component != null) {
326 String[] args = new String[component.getTabCount()];
327
328 // Iterate through the tabbed panes tabs, updating values and recording the original key of each item in args.
329 for (int i = 0; i < args.length; i++) {
330 if (args[i] == null) {
331 args[i] = component.getTitleAt(i);
332 }
333 String value = get(args[i], (String[]) null);
334 String tooltip = get(args[i] + "_Tooltip", (String[]) null);
335 JTabbedPaneChangeTask task = new JTabbedPaneChangeTask(component, i, value, tooltip);
336 SwingUtilities.invokeLater(task);
337 }
338 }
339 }
340
341
342 /** Updates a tabbed panes tab title and tooltip. */
343 static private class JTabbedPaneChangeTask
344 implements Runnable {
345
346 private JTabbedPane component;
347 private int index;
348 private String value;
349 private String tooltip;
350
351 public JTabbedPaneChangeTask(JTabbedPane component, int index, String value, String tooltip) {
352 this.component = component;
353 this.index = index;
354 this.value = value;
355 this.tooltip = tooltip;
356 }
357
358 public void run() {
359 component.setTitleAt(index, value);
360 component.setToolTipTextAt(index, tooltip);
361 }
362 }
363}
Note: See TracBrowser for help on using the repository browser.