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

Last change on this file since 8236 was 8236, checked in by mdewsnip, 20 years ago

Replaced all Gatherer.print* with DebugStream.print*.

  • Property svn:keywords set to Author Date Id Revision
File size: 12.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(Utility.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 setTooltip(component, tooltip_key);
217 }
218
219
220 static public void registerTooltipText(Component component, String tooltip) {
221 setTooltipText(component, tooltip);
222 }
223
224
225 static public void setBoth(Component component, String text_key, String tooltip_key)
226 {
227 setText(component, text_key);
228 setTooltip(component, tooltip_key);
229 }
230
231
232 static public void setText(Component component, String text_key)
233 {
234 setText(component, text_key, null);
235 }
236
237
238 static public void setText(Component component, String text_key, String[] args)
239 {
240 if (component != null) {
241 // Update the component using the AWTEvent queue
242 ComponentDetails details = new ComponentDetails(true, text_key, args, false, null);
243 ComponentUpdateTask task = new ComponentUpdateTask(component, details);
244 SwingUtilities.invokeLater(task);
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 ComponentDetails details = new ComponentDetails(false, null, null, true, tooltip_key);
254 ComponentUpdateTask task = new ComponentUpdateTask(component, details);
255 SwingUtilities.invokeLater(task);
256 }
257 }
258
259
260 static public void setTooltipText(Component component, String tooltip)
261 {
262 if (component != null) {
263 ComponentUpdateTask task = new ComponentUpdateTask(component, null, tooltip);
264 SwingUtilities.invokeLater(task);
265 }
266 }
267
268
269 static private class ComponentDetails
270 {
271 public boolean has_text;
272 public String text_key;
273 public String[] text_args;
274 public boolean has_tooltip;
275 public String tooltip_key;
276
277 public ComponentDetails(boolean has_text, String text_key, String[] text_args,
278 boolean has_tooltip, String tooltip_key)
279 {
280 this.has_text = has_text;
281 this.text_key = text_key;
282 this.text_args = text_args;
283 this.has_tooltip = has_tooltip;
284 this.tooltip_key = tooltip_key;
285 }
286 }
287
288
289 static private class ComponentUpdateTask
290 implements Runnable {
291
292 private Component component;
293 private String text = null;
294 private String tooltip = null;
295
296
297 public ComponentUpdateTask(Component component, ComponentDetails details)
298 {
299 this.component = component;
300
301 if (details.has_text) {
302 text = get(details.text_key, details.text_args);
303 }
304 if (details.has_tooltip) {
305 tooltip = get(details.tooltip_key, (String[]) null);
306 }
307 }
308
309
310 public ComponentUpdateTask(Component component, String text, String tooltip)
311 {
312 this.component = component;
313 this.text = text;
314 this.tooltip = tooltip;
315 }
316
317
318 public void run()
319 {
320 // If the component has text
321 if (text != null) {
322 if (component instanceof AbstractButton) {
323 ((AbstractButton) component).setText(text);
324 }
325 else if (component instanceof Frame) {
326 ((Frame) component).setTitle(text);
327 }
328 else if (component instanceof JDialog) {
329 ((JDialog) component).setTitle(text);
330 }
331 else if (component instanceof JLabel) {
332 ((JLabel) component).setText(text);
333 }
334 else if (component instanceof JProgressBar) {
335 ((JProgressBar) component).setString(text);
336 }
337 else if (component instanceof JTextComponent) {
338 ((JTextComponent) component).setText(text);
339 ((JTextComponent) component).setCaretPosition(0);
340 }
341 else {
342 System.err.println("Unhandled component: " + component.getClass());
343 }
344 }
345
346 // If the component has a tooltip
347 if (tooltip != null) {
348 if (component instanceof JComponent) {
349 ((JComponent) component).setToolTipText(tooltip);
350 }
351 }
352 }
353 }
354
355
356 /**
357 * Register a tab pane component. This will be deprecated eventually. */
358 static public void register(JTabbedPane component)
359 {
360 if (component != null) {
361 String[] args = new String[component.getTabCount()];
362
363 // Iterate through the tabbed panes tabs, updating values and recording the original key of each item in args.
364 for (int i = 0; i < args.length; i++) {
365 if (args[i] == null) {
366 args[i] = component.getTitleAt(i);
367 }
368 String value = get(args[i], (String[]) null);
369 String tooltip = get(args[i] + "_Tooltip", (String[]) null);
370 JTabbedPaneChangeTask task = new JTabbedPaneChangeTask(component, i, value, tooltip);
371 SwingUtilities.invokeLater(task);
372 }
373 }
374 }
375
376
377 /** Updates a tabbed panes tab title and tooltip. */
378 static private class JTabbedPaneChangeTask
379 implements Runnable {
380
381 private JTabbedPane component;
382 private int index;
383 private String value;
384 private String tooltip;
385
386 public JTabbedPaneChangeTask(JTabbedPane component, int index, String value, String tooltip) {
387 this.component = component;
388 this.index = index;
389 this.value = value;
390 this.tooltip = tooltip;
391 }
392
393 public void run() {
394 component.setTitleAt(index, value);
395 component.setToolTipTextAt(index, tooltip);
396 }
397 }
398}
Note: See TracBrowser for help on using the repository browser.