source: trunk/gli/src/org/greenstone/gatherer/cdm/ArgumentControl.java@ 12305

Last change on this file since 12305 was 12305, checked in by kjdon, 18 years ago

removed gui.ArgumentControl class and ArgumentConfiguration inner class Argument control, and added a new class cdm/ArgumentControl.

  • Property svn:keywords set to Author Date Id Revision
File size: 22.3 KB
Line 
1package org.greenstone.gatherer.cdm;
2
3import java.awt.*;
4import java.awt.event.*;
5import javax.swing.*;
6import javax.swing.event.*;
7
8import java.io.File;
9import java.util.ArrayList;
10import java.util.Collections;
11import java.util.Map;
12import java.util.Iterator;
13import java.util.HashMap;
14
15import org.greenstone.gatherer.Configuration;
16import org.greenstone.gatherer.DebugStream;
17import org.greenstone.gatherer.Dictionary;
18import org.greenstone.gatherer.Gatherer;
19import org.greenstone.gatherer.gui.GComboBox;
20import org.greenstone.gatherer.util.StaticStrings;
21import org.greenstone.gatherer.util.Utility;
22import org.greenstone.gatherer.metadata.MetadataElement;
23import org.greenstone.gatherer.metadata.MetadataSet;
24import org.greenstone.gatherer.metadata.MetadataSetManager;
25import org.greenstone.gatherer.metadata.MetadataTools;
26
27/** This class encapsulates all the technical difficulty of creating a specific control based on an Argument. */
28public class ArgumentControl
29 extends JPanel {
30
31 static protected Dimension LABEL_SIZE = new Dimension(175, 25);
32 static protected Dimension ROW_SIZE = new Dimension(800, 30);
33
34 /** The Argument this control will be based on. */
35 private Argument argument = null;
36
37 /** A checkbox to allow enabling or diabling of this Argument. */
38 private JCheckBox enabled = null;
39 /** Some form of editor component, such as a JComboBox or JTextField, used to set parameters to an Argument. */
40 private JComponent value_control = null;
41
42 /** Constructor.
43 */
44 public ArgumentControl(Argument argument, boolean is_enabled, String preset_value) {
45 this.argument = argument;
46 ///ystem.err.println("generating controls for arg "+argument.getName());
47 String tip = "<html>" + argument.getDescription() + "</html>";
48 tip = Utility.formatHTMLWidth(tip, 60);
49
50 setBackground(Configuration.getColor("coloring.collection_tree_background", false));
51 setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
52 setLayout(new BorderLayout());
53 //setPreferredSize(ROW_SIZE);
54 setMaximumSize(ROW_SIZE);
55
56 if (argument.isRequired()) {
57 JLabel label = new JLabel(argument.getName());
58 label.setOpaque(false);
59 label.setPreferredSize(LABEL_SIZE);
60 label.setToolTipText(tip);
61 add(label, BorderLayout.WEST);
62 } else {
63 enabled = new JCheckBox(argument.getName());
64 enabled.setOpaque(false);
65 enabled.setPreferredSize(LABEL_SIZE);
66 enabled.setToolTipText(tip);
67 add(enabled, BorderLayout.WEST);
68 }
69
70 String initial_value;
71 if (preset_value != null && !preset_value.equals("")) {
72 initial_value = preset_value;
73 }
74 else {
75 initial_value = argument.getValue();
76 }
77 if (initial_value == null || initial_value.equals("")) {
78 initial_value = argument.getDefaultValue();
79 }
80 if (initial_value == null) {
81 initial_value = "";
82 }
83
84 switch(argument.getType()) {
85 case Argument.ENUM:
86 // Build an option model, wrapping each entry of the list table.
87 HashMap arg_list = argument.getOptions();
88 ArrayList options_model = new ArrayList();
89 Iterator it = arg_list.entrySet().iterator();
90 while(it.hasNext()) {
91 Map.Entry e = (Map.Entry)it.next();
92 //String key = (String) it.next();
93 //options_model.add(new ListOption(key, (String)arg_list.get(key)));
94 options_model.add(new ListOption((String)e.getKey(), (String)e.getValue()));
95 }
96 Collections.sort(options_model);
97 value_control = new GComboBox(options_model.toArray(), false);
98 ((JComboBox)value_control).addActionListener(new ToolTipUpdater());
99 selectValue((JComboBox)value_control, initial_value);
100 break;
101
102 case Argument.FLAG:
103 // Only need the check box.
104 break;
105
106 case Argument.INTEGER:
107 // Build a spinner
108 int initial_int=0;
109 // If there was an original value, set it.
110 try {
111 initial_int = Integer.parseInt(initial_value);
112 } catch (Exception error) {
113 DebugStream.println("ArgumentControl Error: "+error);
114 }
115 if (initial_int < argument.getMinimum()) {
116 initial_int = argument.getMinimum();
117 } else if (initial_int > argument.getMaximum()) {
118 initial_int = argument.getMaximum();
119 }
120
121 JSpinner spinner = new JSpinner(new SpinnerNumberModel(initial_int, argument.getMinimum(), argument.getMaximum(), 1));
122
123 // And remember it
124 value_control = spinner;
125 break;
126
127 case Argument.REGEXP:
128 case Argument.STRING:
129 value_control = new JTextField(initial_value);
130 break;
131
132 case Argument.LANGUAGE:
133 value_control = new GComboBox(CollectionDesignManager.language_manager.getLanguageCodes().toArray(), false);
134 // we want to display the language name not the code
135 ((JComboBox)value_control).setRenderer(new LanguageListCellRenderer());
136 // Now ensure we have the existing value or default value selected if either exist in our known languages
137 String lang_name = CollectionDesignManager.language_manager.getLanguageName(initial_value);
138 if (lang_name != null) {
139 ((JComboBox)value_control).setSelectedItem(initial_value);
140 }
141 break;
142
143 case Argument.METADATUM:
144 case Argument.METADATA:
145 value_control = new GComboBox(MetadataSetManager.getEveryMetadataSetElement(), false);
146
147 // Editable for advanced modes (allows things like dc.Title,ex.Title)
148 if (Configuration.getMode() > Configuration.ASSISTANT_MODE) {
149 ((JComboBox) value_control).setEditable(true);
150 }
151
152 // Now ensure we have the existing value or default value selected if either exist.
153 String existing_value = argument.getValue();
154 if (existing_value != null && existing_value.length() > 0) {
155 boolean found = selectValue((JComboBox) value_control, existing_value);
156 // It's possible that this is a custom value and so doesn't exist in the combobox
157 if (!found) {
158 // If so, add it then select it
159 ((JComboBox) value_control).addItem(existing_value);
160 ((JComboBox) value_control).setSelectedItem(existing_value);
161 }
162 }
163 else {
164 String default_value = argument.getDefaultValue();
165 if (default_value != null) {
166 // if no namespace for default value, add ex.
167 // won't work if we want to set a non-metadata value
168 if (MetadataTools.getMetadataSetNamespace(default_value).equals("")) {
169 default_value = StaticStrings.EXTRACTED_NAMESPACE+default_value;
170 }
171 selectValue((JComboBox) value_control, default_value);
172 }
173 }
174 break;
175
176 case Argument.METADATA_SET_NAMESPACE:
177 value_control = new JComboBox();
178 // !! Hack for exploding metadata databases: add the (empty) exploded metadata set
179 File exploded_metadata_set_file = new File(Gatherer.getGLIMetadataDirectoryPath() + "exp" + StaticStrings.METADATA_SET_EXTENSION);
180 MetadataSet exploded_metadata_set = new MetadataSet(exploded_metadata_set_file);
181 Gatherer.c_man.importMetadataSet(exploded_metadata_set);
182
183 // All the loaded metadata sets except the extracted metadata set are applicable
184 ArrayList metadata_sets = MetadataSetManager.getMetadataSets();
185 for (int i = metadata_sets.size() - 1; i >= 0; i--) {
186 MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
187 if (!(metadata_set.getNamespace().equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE))) {
188 ((JComboBox)value_control).addItem(metadata_set);
189 }
190 }
191 } // end of switch
192
193 // Enable or disable as necessary.
194 if(argument.isRequired() || argument.isAssigned() || is_enabled) {
195 if (enabled != null) {
196 enabled.setSelected(true);
197 }
198 if(value_control != null) {
199 value_control.setOpaque(true);
200 value_control.setBackground(Color.white);
201 value_control.setEnabled(true);
202 if(value_control instanceof JSpinner) {
203 // Set enabled
204 JComponent c = ((JSpinner)value_control).getEditor();
205 if ( c instanceof JSpinner.DefaultEditor ) {
206 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
207 JFormattedTextField field = editor.getTextField();
208 field.setEditable(true);
209 field.setBackground(Color.white);
210 }
211 }
212 }
213 }
214 else {
215 if (enabled != null) {
216 enabled.setSelected(false);
217 }
218 if(value_control != null) {
219 value_control.setOpaque(true);
220 value_control.setBackground(Color.lightGray);
221 value_control.setEnabled(false);
222 if(value_control instanceof JSpinner) {
223 // Set enabled
224 JComponent c = ((JSpinner)value_control).getEditor();
225 if ( c instanceof JSpinner.DefaultEditor ) {
226 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
227 JFormattedTextField field = editor.getTextField();
228 field.setEditable(false);
229 field.setBackground(Color.lightGray);
230 }
231 }
232 }
233 }
234
235 // Listener
236 if(value_control != null) {
237 value_control.setToolTipText(tip);
238 add(value_control, BorderLayout.CENTER);
239 if (!argument.isRequired()) {
240 enabled.addActionListener(new EnabledListener(value_control));
241 }
242 }
243 }
244
245 public Argument getArgument() {
246 return argument;
247 }
248
249 public String getArgumentName() {
250 return argument.getName();
251 }
252
253 public String getValue() {
254 if(value_control == null) {
255 return null;
256 }
257 if (value_control instanceof JSpinner) {
258 return ((JSpinner)value_control).getValue().toString();
259 }
260 if(value_control instanceof JComboBox) {
261 Object selected_item = ((JComboBox)value_control).getSelectedItem();
262 if (selected_item != null) {
263 if (argument.getType() == Argument.METADATA_SET_NAMESPACE) {
264 return ((MetadataSet) selected_item).getNamespace();
265 }
266 if (selected_item instanceof ListOption) {
267 return ((ListOption)selected_item).getValue();
268 }
269 return selected_item.toString();
270 }
271
272 return null;
273 }
274 if(value_control instanceof JTextField) {
275 return ((JTextField)value_control).getText();
276 }
277 return null;
278 }
279 /** Retrieve the control used for storing values.
280 * @return JComponent
281 */
282 public JComponent getValueControl() {
283 return value_control;
284 }
285
286 public boolean isEnabled() {
287 if (enabled == null) {
288 return true; // always enabled
289 }
290 return enabled.isSelected();
291 }
292
293
294 /** Identifies this control by returning the name of the Argument it is based on.
295 * @return The name of the Argument as a <strong>String</strong>.
296 * @see org.greenstone.gatherer.cdm.Argument
297 */
298 public String toString() {
299 return argument.getName();
300 }
301 /** Updates the enwrapped Argument using the values provided by the controls.
302 * @return <i>true</i> if the update was successful, <i>false</i> otherwise.
303 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption
304 * @see org.greenstone.gatherer.cdm.Language
305 */
306 public boolean updateArgument() {
307 if(enabled.isSelected() || argument.isRequired()) {
308 argument.setAssigned(false);
309 String result = null;
310 switch(argument.getType()) {
311 case Argument.ENUM:
312 ListOption option = (ListOption)((JComboBox)value_control).getSelectedItem();
313 if(option != null && option.getValue().length() > 0) {
314 argument.setValue(option.getValue());
315 }
316 else {
317 String args[] = new String[1];
318 args[0] = argument.getName();
319 if(argument.isRequired()) {
320 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
321 }
322 // They've left the field blank
323 else {
324 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
325 argument.setValue(null);
326 }
327 args = null;
328 return false;
329 }
330 argument.setAssigned(true);
331 return true;
332 case Argument.FLAG:
333 // Should have already been handled above.
334 argument.setAssigned(true);
335 return true;
336 case Argument.INTEGER:
337 result = ((JSpinner)value_control).getValue().toString();
338 if(result.length() > 0) {
339 // Test if the value entered is a valid int.
340 try {
341 int x = Integer.parseInt(result);
342 }
343 catch(NumberFormatException nfe) {
344 String args[] = new String[2];
345 args[0] = argument.getName();
346 args[1] = result;
347 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Bad_Integer", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
348 args = null;
349 return false;
350 }
351 argument.setValue(result);
352 }
353 else {
354 String args[] = new String[1];
355 args[0] = argument.getName();
356 if(argument.isRequired()) {
357 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
358 }
359 // They've left the field blank
360 else {
361 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
362 argument.setValue(null);
363 }
364 args = null;
365 return false;
366 }
367 argument.setAssigned(true);
368 return true;
369 case Argument.LANGUAGE:
370 String language = (((JComboBox)value_control).getSelectedItem()).toString();
371 argument.setValue(language);
372 // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
373 argument.setAssigned(true);
374 return true;
375 case Argument.METADATUM:
376 case Argument.METADATA:
377 Object new_value_raw = ((JComboBox) value_control).getSelectedItem();
378 if (new_value_raw instanceof MetadataElement) {
379 argument.setValue(((MetadataElement) new_value_raw).getFullName());
380 }
381 else {
382 // But we have to be careful as an arbitary string object could be zero length
383 String new_value = new_value_raw.toString();
384 ///ystem.err.println("The current value is: " + new_value);
385 if(new_value.length() > 0) {
386 argument.setValue(new_value);
387 }
388 else {
389 String args[] = new String[1];
390 args[0] = argument.getName();
391 if(argument.isRequired()) {
392 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
393 }
394 // They've left the field blank
395 else {
396 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
397 argument.setValue(null);
398 }
399 args = null;
400 return false;
401 }
402 }
403 argument.setAssigned(true);
404 return true;
405 // case Argument.METADATA:
406 // DefaultListModel model = (DefaultListModel)list.getModel();
407 // ArrayList values = new ArrayList();
408 // for(int i = 0; i < model.size(); i++) {
409 // values.add(model.get(i));
410 // }
411 // argument.setValues(values);
412 // argument.setAssigned(true);
413 // return true;
414 case Argument.HIERARCHY:
415 // argument.setValue(((JComboBox)value).getSelectedItem().toString());
416 // // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
417 // argument.setAssigned(true);
418 return true;
419 case Argument.REGEXP:
420 case Argument.STRING:
421 result = ((JTextField)value_control).getText();
422 if(result.length() > 0) {
423 argument.setValue(result);
424 }
425 else {
426 String args[] = new String[1];
427 args[0] = argument.getName();
428 if(argument.isRequired()) {
429 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
430 }
431 // They've left the field blank
432 else {
433 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
434 argument.setValue(null);
435 }
436 args = null;
437 return false;
438 }
439 argument.setAssigned(true);
440 return true;
441 }
442 return false;
443 }
444 else {
445 argument.setAssigned(false);
446 return true;
447 }
448 }
449 /** Method to ensure that a certain value is selected, if it exists within that combobox to begin with.
450 * @param combobox The <strong>JComboBox</strong> whose selection we are trying to preset.
451 * @param target The desired value of the selection as a <strong>String</strong>.
452 * @return true if the item was found and selected, false otherwise
453 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption
454 */
455 public boolean selectValue(JComboBox combobox, String target) {
456 ///ystem.err.println("Searching for the target string: " + target);
457 for(int i = 0; i < combobox.getItemCount(); i++) {
458 Object object = combobox.getItemAt(i);
459 if(object instanceof ListOption) {
460 ListOption lo = (ListOption) object;
461 ///ystem.err.print("/tChecking: " + lo.getValue() + "... ");
462 if(lo.getValue().startsWith(target)) {
463 ///ystem.err.println("Match!");
464 combobox.setSelectedIndex(i);
465 return true;
466 }
467 /*
468 else {
469 System.err.println("No Match.");
470 }
471 */
472 }
473 else if (object instanceof MetadataElement) {
474 if(object.toString().equals(target)) {
475 combobox.setSelectedIndex(i);
476 return true;
477 }
478 }
479 }
480 return false;
481 }
482 /** Forces the control into an 'enabled' mode. */
483 public void setEnabled() {
484 enabled.setSelected(true);
485 }
486 /** Explicitly sets the value of a JTextField type control to the given String.
487 * @param value_str The new value of the control as a <strong>String</strong>.
488 */
489 public void setValue(String value_str) {
490 ((JTextField)value_control).setText(value_str);
491 }
492
493 /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
494 private class EnabledListener
495 implements ActionListener {
496 /** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
497 private JComponent target = null;
498
499 /** Constructor. */
500 public EnabledListener(JComponent target) {
501 this.target = target;
502 }
503
504 /** Any implementation of ActionListener must include this method so that we can be informed when an action has been performed on or registered check box, prompting us to change the state of the other controls as per the users request.
505 * @param event An <strong>ActionEvent</strong> containing information about the click.
506 */
507 public void actionPerformed(ActionEvent event) {
508 if (this.target == null) {
509 return;
510 }
511 JCheckBox source = (JCheckBox)event.getSource();
512 if(source.isSelected()) {
513 target.setBackground(Color.white);
514 target.setEnabled(true);
515 }
516 else {
517 target.setBackground(Color.lightGray);
518 target.setEnabled(false);
519 }
520 // Special case of stupid JSpinners who don't let their backgrounds change properly.
521 if(target instanceof JSpinner) {
522 JSpinner spinner = (JSpinner) target;
523 JComponent c = spinner.getEditor();
524 if ( c instanceof JSpinner.DefaultEditor ) {
525 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
526 JFormattedTextField field = editor.getTextField();
527 field.setEditable(source.isSelected());
528 if(source.isSelected()) {
529 field.setBackground(Color.white);
530 }
531 else {
532 field.setBackground(Color.lightGray);
533 }
534 }
535 }
536 }
537 }
538
539
540
541 /** A ListOption is a compound item which is constructed from several Strings. That magic part is that the length of screen real-estate used by the text version of this item is limited. */
542 private class ListOption
543 implements Comparable {
544 /** The maximum length of this String version of this item. */
545 private int MAX_DESC = 47;
546 /** The description of the value for this item. */
547 private String description = null;
548 /** A cached value for the text value of this option, as it never changes after the first call to toString(). */
549 private String text = null;
550 /** The value for this item. */
551 private String value = null;
552 /** Constructor.
553 * @param value The value for this item as a <strong>String</strong>.
554 * @param description The description of the value as a <strong>String</strong>.
555 */
556 public ListOption(String value, String description) {
557 this.description = description;
558 this.value = value;
559 }
560 /** Compare two possible ListOption objects for ordering.
561 * @param object The <strong>Object</strong> to compare to.
562 * @return An <i>int</i> indicating order as explained in String.
563 * @see java.lang.String#compareTo
564 */
565 public int compareTo(Object object) {
566 return toString().compareTo(object.toString());
567 }
568 /** Tests two possible ListOption objects for equality. Uses the result from compareTo().
569 * @param object The <strong>Object</strong> which may be equal.
570 * @return <i>true</i> if the objects are equal, <i>false</i> otherwise.
571 */
572 public boolean equals(Object object) {
573 return (object != null && compareTo(object) == 0);
574 }
575 /** Retrieve the description of this list item.
576 * @return The description as a <strong>String</strong>.
577 */
578 public String getDesc() {
579 return description;
580 }
581 /** Retrieve the value of this list item.
582 * @return The value as a <strong>String</strong>.
583 */
584 public String getValue() {
585 return value;
586 }
587 /** Convert this object into a nice readable String.
588 * @return A <strong>String</strong> representing this object.
589 */
590 public String toString() {
591 if(text == null) {
592 if(value.length() + description.length() >= MAX_DESC) {
593 text = value + " "+ StaticStrings.MINUS_CHARACTER + " "+ description.substring(0, MAX_DESC-value.length()) + StaticStrings.TRUNCATED_STRING;
594 }
595 else {
596 text = value + " "+ StaticStrings.MINUS_CHARACTER + " "+ description;
597 }
598 }
599 return text;
600 }
601 }
602
603
604 /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
605 private class ToolTipUpdater
606 implements ActionListener {
607 /** Any implementation of an ActionListener must include this method so that we can be informed when the selection in a combobox has changed and update the tooltip accordingly.
608 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
609 */
610 public void actionPerformed(ActionEvent event) {
611 JComboBox source = (JComboBox)event.getSource();
612 Object object = source.getSelectedItem();
613 if(object instanceof ListOption) {
614 ListOption lo = (ListOption)object;
615 if(lo != null) {
616 String description = Utility.formatHTMLWidth(lo.getDesc(), 60);
617 source.setToolTipText(description);
618 }
619 else {
620 source.setToolTipText(StaticStrings.EMPTY_STR);
621 }
622 }
623 }
624 }
625}
Note: See TracBrowser for help on using the repository browser.