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

Last change on this file since 18911 was 18911, checked in by kjdon, 15 years ago

added support for new plugin option type: enumstring, which has a list of predefined values, but can actually take any value - an editbale combobox in gli

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