source: trunk/gli/src/org/greenstone/gatherer/cdm/LanguageManager.java@ 4675

Last change on this file since 4675 was 4675, checked in by jmt12, 21 years ago

Sunday's work

  • Property svn:keywords set to Author Date Id Revision
File size: 25.1 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 */
37
38
39
40
41
42
43package org.greenstone.gatherer.cdm;
44/**************************************************************************************
45 * Title: Gatherer
46 * Description: The Gatherer: a tool for gathering and enriching a digital collection.
47 * Copyright: Copyright (c) 2001
48 * Company: The University of Waikato
49 * Written: 08/05/02
50 * Revised: 17/11/02 - Commented
51 **************************************************************************************/
52import java.awt.BorderLayout;
53import java.awt.Color;
54import java.awt.Component;
55import java.awt.Dimension;
56import java.awt.GridLayout;
57import java.awt.event.ActionEvent;
58import java.awt.event.ActionListener;
59import java.awt.event.KeyEvent;
60import java.io.BufferedReader;
61import java.io.File;
62import java.io.FileReader;
63import java.util.ArrayList;
64import java.util.Collections;
65import java.util.Enumeration;
66import java.util.Iterator;
67import java.util.LinkedHashMap;
68import java.util.StringTokenizer;
69import java.util.Vector;
70import javax.swing.BorderFactory;
71import javax.swing.DefaultListCellRenderer;
72import javax.swing.DefaultListModel;
73import javax.swing.ListModel;
74import javax.swing.JButton;
75import javax.swing.JComboBox;
76import javax.swing.JLabel;
77import javax.swing.JList;
78import javax.swing.JPanel;
79import javax.swing.JScrollPane;
80import javax.swing.JTextArea;
81import javax.swing.JTextField;
82import javax.swing.event.ListSelectionEvent;
83import javax.swing.event.ListSelectionListener;
84import org.greenstone.gatherer.Gatherer;
85import org.greenstone.gatherer.cdm.Language;
86/** This class manages the language commands, remembering both a list of languages to build indexes in, plus the default language.
87 * @author John Thompson, Greenstone Digital Library, University of Waikato
88 * @version 2.3
89 */
90public class LanguageManager
91 extends DefaultListModel {
92 /** A reference to the collection design manager. */
93 private CollectionDesignManager manager = null;
94 /** The visual controls for this manager. */
95 private Control controls = null;
96 /** A reference to the Gatherer. */
97 private Gatherer gatherer = null;
98 /** A reference to this class as a model, for the inner controls class. */
99 private ListModel model = null;
100 /** A hashtable of code->name mappings of known languages. */
101 private LinkedHashMap known_languages = null;
102 /** The default language object. */
103 private Language default_language = null;
104
105 static final private Dimension LABEL_SIZE = new Dimension(125,25);
106 /** Constructor.
107 * @param gatherer A reference to the <strong>Gatherer</strong>.
108 * @param manager A reference to the <strong>CollectionDesignManager</strong>.
109 */
110 public LanguageManager(Gatherer gatherer, CollectionDesignManager manager) {
111 super();
112 this.gatherer = gatherer;
113 this.known_languages = new LinkedHashMap();
114 this.manager = manager;
115 this.model = this;
116 loadLanguages();
117 }
118 /** Method to add a new language.
119 * @param language The <strong>Language</strong> to add.
120 * @see org.greenstone.gatherer.Gatherer
121 * @see org.greenstone.gatherer.collection.CollectionManager
122 */
123 public void addLanguage(Language language) {
124 if(!contains(language)) {
125 // Add alphabetically.
126 for(int index = 0; index < size(); index++) {
127 Language sibling = (Language) get(index);
128 int position = language.compareTo(sibling);
129 // Sibling is before language.
130 if(position > 0) {
131 // Carry on.
132 }
133 // Language is equal to, or before sibling. Insert it.
134 else if(position == 0 || position < 0) {
135 add(index, language);
136 gatherer.c_man.configurationChanged();
137 return;
138 }
139 }
140 // If we got this far, we haven't inserted language, and we are out of model so.
141 addElement(language);
142 gatherer.c_man.configurationChanged();
143 }
144 }
145 /** Method to retrieve the control for this manager.
146 * @return A <strong>JPanel</strong> containing the controls.
147 */
148 public JPanel getControls() {
149 if(controls == null) {
150 controls = new Control();
151 }
152 return controls;
153 }
154 /** Method to retrieve the default language code.
155 * @return A <strong>Language</strong> containing a two letter code.
156 */
157 public Language getDefaultLanguage() {
158 // If no default is set...
159 if(default_language == null) {
160 // And we have other assigned languages, use the first one of them.
161 if(size() >= 1) {
162 default_language = (Language) get(0);
163 }
164 // And we have nothing else, use English.
165 else {
166 default_language = getLanguage("en", false);
167 // Remember to add it.
168 addLanguage(default_language);
169 }
170 }
171 return default_language;
172 }
173 /** Method to retrieve a certain language object by its code.
174 * @param code The two letter code of a language, as a <strong>String</strong>.
175 * @param assigned_only If <i>true</i> only those languages currently having indexes built for them are checked, otherwise the known languages buffer is checked.
176 * @return The <strong>Language</strong> that matches the given code, or <i>null</i> if no such language exists.
177 */
178 public Language getLanguage(String code, boolean assigned_only) {
179 if(assigned_only) {
180 for(int i = 0; i < size(); i++) {
181 Language pos = (Language)get(i);
182 ///ystem.err.println("Comparing " + pos.getCode() + " and " + code);
183 if(pos.getCode().equals(code)) {
184 return pos;
185 }
186 }
187 }
188 else {
189 if(known_languages.containsKey(code)) {
190 return new Language((Language)known_languages.get(code));
191 }
192 }
193 return null;
194 }
195 /** Method to return a list of the known language codes.
196 * @return An <strong>ArrayList</strong> containing a series of alphabetically sorted two letter codes.
197 */
198 public ArrayList getLanguageCodes() {
199 ArrayList result = new ArrayList();
200 Iterator key_iter = known_languages.keySet().iterator();
201 while(key_iter.hasNext()) {
202 result.add(known_languages.get(key_iter.next()));
203 }
204 //for(Enumeration keys = known_languages.keys(); keys.hasMoreElements(); ) {
205 // result.add(known_languages.get(keys.nextElement()));
206 //}
207 //Collections.sort(result);
208 return result;
209 }
210 /** Mark the current set of controls, if any, as obsolete and deallocate them. If further need of the controls will cause new controls to be created.
211 * @see org.greenstone.gatherer.cdm.IndexManager.Control
212 */
213 public void invalidateControls() {
214 if(controls != null) {
215 controls.destroy();
216 }
217 controls = null;
218 }
219
220 /** Determine if the given language is the current default language.
221 * @param language The <strong>Language</strong> to test.
222 * @return <i>true</i> if the language is the default one, <i>false</i> otherwise.
223 */
224 public boolean isDefaultLanguage(Language language) {
225 return (language.equals(default_language));
226 }
227 /** This method attempts to parse a language command from the given string. If such a command is parsed, it is immediately added to the list of languages.
228 * @param command The <strong>String</strong> containing a possible language command.
229 * @return A <i>boolean</i> which is <i>true</i> if a command was parsed, <i>false</i> otherwise.
230 * @see org.greenstone.gatherer.cdm.Language
231 */
232 public boolean parse(String command) {
233 String command_lc = command.toLowerCase();
234 if(command_lc.startsWith("languages")) {
235 StringTokenizer tokenizer = new StringTokenizer(command);
236 tokenizer.nextToken();
237 while(tokenizer.hasMoreTokens()) {
238 String code = tokenizer.nextToken();
239 if(known_languages.containsKey(code)) {
240 Language language = (Language)known_languages.get(code);
241 addElement(new Language(language));
242 }
243 else {
244 addElement(new Language(code, code, false));
245 }
246 }
247 return true;
248 }
249 if(command_lc.startsWith("defaultlanguage")) {
250 StringTokenizer tokenizer = new StringTokenizer(command);
251 tokenizer.nextToken();
252 if(tokenizer.hasMoreTokens()) {
253 String code = tokenizer.nextToken();
254 Language language = getLanguage(code, true);
255 if(language == null) {
256 language = new Language(code, (String)known_languages.get(code), true);
257 addElement(language);
258 }
259 else {
260 language.setDefault(true);
261 }
262 setDefault(language);
263 }
264 return true;
265 }
266 return false;
267 }
268 /** Method to cause the list appearance to update if the selection changes. */
269 public void refreshAppearance() {
270 fireContentsChanged(this, 0, size());
271 }
272 /** Method to remove a certain language.
273 * @param language The <strong>Language</strong> to remove.
274 * @see org.greenstone.gatherer.Gatherer
275 * @see org.greenstone.gatherer.collection.CollectionManager
276 */
277 public void removeLanguage(Language language) {
278 removeElement(language);
279 if(default_language != null && default_language.equals(language)) {
280 default_language = null;
281 }
282 gatherer.c_man.configurationChanged();
283 }
284 /** Method to set the default language.
285 * @param language The <strong>Language</strong> to use as a default, or <i>null</i> for no default.
286 * @see org.greenstone.gatherer.Gatherer
287 * @see org.greenstone.gatherer.collection.CollectionManager
288 */
289 public void setDefault(Language language) {
290 // Unset existing.
291 Language old = null;
292 if(default_language != null) {
293 old = default_language;
294 default_language.setDefault(false);
295 default_language = null;
296 }
297 // Now set the new if its not null.
298 if(language != null) {
299 default_language = language;
300 default_language.setDefault(true);
301 }
302 // Now cause the model to refresh any lists that are listening.
303 int start = 0;
304 int end = size() - 1;
305 if(default_language != null && old != null) {
306 int index_default = indexOf(default_language);
307 int index_old = indexOf(old);
308 if(index_default < index_old) {
309 start = index_default;
310 end = index_old;
311 }
312 else {
313 start = index_old;
314 end = index_default;
315 }
316 }
317 else if(default_language != null) {
318 start = end = indexOf(default_language);
319 }
320 else {
321 start = end = indexOf(old);
322 }
323 fireContentsChanged(this, 0, size());
324 gatherer.c_man.configurationChanged();
325 }
326 /** Method to translate this object into a block of commands as you you expect to find in the collection configuration file.
327 * @return A <strong>String</string> containing a series of commands.
328 */
329 public String toString() {
330 StringBuffer text = new StringBuffer();
331 if(size() > 1) {
332 text.append("languages ");
333 for(int i = 0; i < size(); i++) {
334 Language language = (Language) get(i);
335 text.append(language.getCode());
336 if(i < size() - 1) {
337 text.append(" ");
338 }
339 else {
340 text.append("\n");
341 }
342 }
343 // Only bother with default language if there is more than one language.
344 if(default_language != null) {
345 text.append("defaultlanguage ");
346 text.append(default_language.getCode());
347 text.append("\n");
348 }
349 text.append("\n");
350 }
351 return text.toString();
352 }
353 /** Overloaded to call get with both a key and an empty argument array.
354 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle.
355 * @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.
356 */
357 private String get(String key) {
358 return get(key, null);
359 }
360 /** 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>
361 * 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>.
362 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle.
363 * @param args A <strong>String[]</strong> used to populate argument fields within the complete String.
364 * @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.
365 * @see org.greenstone.gatherer.Gatherer
366 * @see org.greenstone.gatherer.Dictionary
367 */
368 private String get(String key, String args[]) {
369 if(key.indexOf('.') == -1) {
370 key = "CDM.LanguageManager." + key;
371 }
372 return gatherer.dictionary.get(key, args);
373 }
374 /** This method loads a series of code->language mappings into known_languages, by reading from the 'languages.dat' file, which is essentially a verbatim copy of the ISO 639 Standard.
375 * @see org.greenstone.gatherer.cdm.Language
376 */
377 private void loadLanguages() {
378 try {
379 File in_file = new File("languages.dat");
380 FileReader in_reader = new FileReader(in_file);
381 BufferedReader in = new BufferedReader(in_reader);
382 String entry = null;
383 while((entry = in.readLine()) != null) {
384 if(!entry.startsWith("#")) {
385 StringTokenizer tokenizer = new StringTokenizer(entry);
386 String name = tokenizer.nextToken();
387 String code = tokenizer.nextToken().toLowerCase();
388 Language language = new Language(code, name, false);
389 known_languages.put(code, language);
390 }
391 }
392 in.close();
393 }
394 catch (Exception error) {
395 error.printStackTrace();
396 }
397 }
398
399 /** This class represents the visual component of the Language Manager. */
400 private class Control
401 extends JPanel {
402 /** The button to add a new language support. */
403 private JButton add = null;
404 /** The button to clear the current default language. */
405 private JButton clear_default = null;
406 /** The button to remove a supported language. */
407 private JButton remove = null;
408 /** The button to set the current language as the default one. */
409 private JButton set_default = null;
410 /** A combobox listing the available supported languages. */
411 private JComboBox selector = null;
412 /** A list of currently supported languages. */
413 private JList list = null;
414 /** A description of the language currently selected. */
415 private JTextArea description = null;
416 /** The text field showing the currently name of the default language. Non-editable. */
417 private JTextField default_language_value = null;
418 /** Constructor.
419 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.AddListener
420 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.ClearDefaultListener
421 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.ListListener
422 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.RemoveListener
423 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.SelectorListener
424 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.SetDefaultListener
425 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.TranslateListener
426 */
427 public Control() {
428 super();
429 // Creation.
430 JPanel center_panel = new JPanel();
431
432 JLabel title_label = new JLabel(get("Title"));
433 title_label.setHorizontalAlignment(JLabel.CENTER);
434 title_label.setOpaque(true);
435
436 list = new JList(model);
437 list.setCellRenderer(new ListRenderer());
438
439 JPanel details_panel = new JPanel();
440
441 JPanel default_panel = new JPanel();
442
443 JLabel default_label = new JLabel(get("Default_Language"));
444 default_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
445 default_label.setPreferredSize(LABEL_SIZE);
446
447 if(default_language == null) {
448 default_language_value = new JTextField();
449 }
450 else {
451 default_language_value = new JTextField(default_language.toString());
452 }
453 default_language_value.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
454 default_language_value.setEditable(false);
455
456 JPanel control_panel = new JPanel();
457
458 JLabel selector_label = new JLabel(get("Selector"));
459 selector_label.setPreferredSize(LABEL_SIZE);
460
461 selector = new JComboBox(getLanguageCodes().toArray());
462 selector.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
463
464 JPanel button_panel = new JPanel();
465
466 add = new JButton(get("Add"));
467 add.setMnemonic(KeyEvent.VK_A);
468 if(selector.getSelectedItem() != null) {
469 add.setEnabled(true);
470 }
471 else {
472 add.setEnabled(false);
473 }
474
475 remove = new JButton(get("Remove"));
476 remove.setMnemonic(KeyEvent.VK_R);
477 remove.setEnabled(false);
478
479 clear_default = new JButton(get("Clear_Default"));
480 clear_default.setMnemonic(KeyEvent.VK_C);
481 clear_default.setEnabled(false);
482
483 set_default = new JButton(get("Set_Default"));
484 set_default.setMnemonic(KeyEvent.VK_S);
485 set_default.setEnabled(false);
486
487 // Set up and connect listeners.
488 add.addActionListener(new AddListener());
489 clear_default.addActionListener(new ClearDefaultListener());
490 remove.addActionListener(new RemoveListener());
491 selector.addActionListener(new SelectorListener());
492 set_default.addActionListener(new SetDefaultListener());
493 list.addListSelectionListener(new ListListener());
494 // Layout components.
495 default_panel.setBorder(BorderFactory.createRaisedBevelBorder());
496 default_panel.setLayout(new BorderLayout());
497 default_panel.add(default_label, BorderLayout.WEST);
498 default_panel.add(default_language_value, BorderLayout.CENTER);
499
500 control_panel.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
501 control_panel.setLayout(new BorderLayout());
502 control_panel.add(selector_label, BorderLayout.WEST);
503 control_panel.add(selector, BorderLayout.CENTER);
504
505 details_panel.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
506 details_panel.setLayout(new BorderLayout());
507 details_panel.add(default_panel, BorderLayout.CENTER);
508 details_panel.add(control_panel, BorderLayout.SOUTH);
509
510 center_panel.setLayout(new BorderLayout());
511 center_panel.add(title_label, BorderLayout.NORTH);
512 center_panel.add(new JScrollPane(list), BorderLayout.CENTER);
513 center_panel.add(details_panel, BorderLayout.SOUTH);
514
515 button_panel.setLayout(new GridLayout(2,2,5,5));
516 button_panel.add(add);
517 button_panel.add(remove);
518 button_panel.add(clear_default);
519 button_panel.add(set_default);
520
521 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
522 setLayout(new BorderLayout());
523 add(center_panel, BorderLayout.CENTER);
524 add(button_panel, BorderLayout.SOUTH);
525 }
526 /** Destructor.
527 */
528 public void destroy() {
529 }
530 /** Listens for actions apon the 'add' button in the LanguageManager controls, and if detected calls the add method of the manager with a newly created language. */
531 private class AddListener
532 implements ActionListener {
533 /** Add a new language support.
534 * @param event an ActionEvent
535 * @see org.greenstone.gatherer.cdm.Language
536 */
537 public void actionPerformed(ActionEvent event) {
538 Language language = (Language)selector.getSelectedItem();
539 if(language != null) {
540 addLanguage(new Language(language));
541 }
542 }
543 }
544 /** Listens for actions apon the 'clear default' button in the LanguageManager controls, and if detected calls the setDefault method of the manager with <i>null</i>. */
545 private class ClearDefaultListener
546 implements ActionListener {
547 /** Clear the default index.
548 * @param event An <strong>ActionEvent</strong>.
549 */
550 public void actionPerformed(ActionEvent event) {
551 setDefault(null);
552 clear_default.setEnabled(false);
553 default_language_value.setText("");
554 }
555 }
556 /** Listens for actions apon the 'remove' button in the LanguageManager controls, and if detected calls the remove method of the manager with the language selected for removal. */
557 private class RemoveListener
558 implements ActionListener {
559 /** Remove the currently selected language, if any.
560 * @param event An <strong>ActionEvent</strong>.
561 * @see org.greenstone.gatherer.cdm.Language
562 */
563 public void actionPerformed(ActionEvent event) {
564 if(!list.isSelectionEmpty()) {
565 removeLanguage((Language)list.getSelectedValue());
566 if(default_language == null) {
567 clear_default.setEnabled(false);
568 default_language_value.setText("");
569 }
570 }
571 }
572 }
573 /** Listens for selections wihtin the combobox on the LanguageManager controls, and if a change is detected enables, or disables, controls appropriately. */
574 private class SelectorListener
575 implements ActionListener {
576 /** Enable or disable controls depeding on selection.
577 * @param event An <strong>ActionEvent</strong>.
578 */
579 public void actionPerformed(ActionEvent event) {
580 if(selector.getSelectedItem() != null) {
581 add.setEnabled(true);
582 //description.setText((String)known_languages.get(code));
583 }
584 else {
585 add.setEnabled(false);
586 //description.setText("");
587 }
588 }
589 }
590 /** Listens for actions apon the 'set default' button in the LanguageManager controls, and if detected calls the <i>setDefault()</i> method of the manager with the language selected for default. */
591 private class SetDefaultListener
592 implements ActionListener {
593 /** Set the default index to the one currently selected, if any.
594 * @param event An <strong>ActionEvent</strong>.
595 * @see org.greenstone.gatherer.cdm.Language
596 */
597 public void actionPerformed(ActionEvent event) {
598 if(!list.isSelectionEmpty()) {
599 setDefault((Language)list.getSelectedValue());
600 clear_default.setEnabled(true);
601 default_language_value.setText(default_language.toString());
602 }
603 }
604 }
605 /** Listens for selections within the list on the LanguageManager controls, and if a change is detected enables, or disables, controls appropriately. */
606 private class ListListener
607 implements ListSelectionListener {
608 /** Enable or disable controls depending on the current list selection.
609 * @param event A <strong>ListSelectionEvent</strong>.
610 */
611 public void valueChanged(ListSelectionEvent event) {
612 if(list.isSelectionEmpty()) {
613 remove.setEnabled(false);
614 set_default.setEnabled(false);
615 }
616 else {
617 remove.setEnabled(true);
618 set_default.setEnabled(true);
619 }
620 refreshAppearance();
621 }
622 }
623 /** Our list cel renderer which renders the default cell just a little different. */
624 private class ListRenderer
625 extends DefaultListCellRenderer {
626 /** Method to produce the component used to display an entry in the list.
627 * @param list The <strong>JList</strong> the component will be placed in.
628 * @param value A value to be displayed for this component, as a <strong>Object</strong>.
629 * @param index The position in the list it will occupy as an <i>int</i>.
630 * @param isSelected Whether the user has currently selected this component, as a <i>boolean</i>.
631 * @param cellHasFocus Whether the component currently has focus, again as a <i>boolean</i>.
632 * @return A <strong>Component</strong> to be used as the entry in the list.
633 * @see org.greenstone.gatherer.cdm.Language
634 */
635 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
636 Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
637 Language language = (Language) value;
638 if(language.isDefault() && !isSelected) {
639 component.setBackground(Gatherer.config.getColor("coloring.workspace_selection_background", false));
640 }
641 if(component instanceof JLabel) {
642 ((JLabel)component).setOpaque(true);
643 }
644 return component;
645 }
646 }
647 }
648}
649
650
651
652
653
654
655
Note: See TracBrowser for help on using the repository browser.