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

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

removed metadatum type arg - I don't think it is ever used. and what was it anyway??

  • Property svn:keywords set to Author Date Id Revision
File size: 21.0 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.METADATA:
158 value_control = new GComboBox(MetadataSetManager.getEveryMetadataSetElement(), false);
159 value_control.setComponentOrientation(Dictionary.getOrientation());
160 // Editable for advanced modes (allows things like dc.Title,ex.Title)
161 if (Configuration.getMode() > Configuration.ASSISTANT_MODE) {
162 ((JComboBox) value_control).setEditable(true);
163 }
164 // Now ensure we have the existing value or default value selected if either exist.
165 String existing_value = preset_value;
166 if (existing_value == null || existing_value.length() == 0) {
167 existing_value = argument.getValue();
168 }
169 if (existing_value != null && existing_value.length() > 0) {
170 found = selectValue((JComboBox) value_control, existing_value);
171 // It's possible that this is a custom value and so doesn't exist in the combobox
172 if (!found) {
173 // If so, add it then select it
174 ((JComboBox) value_control).addItem(existing_value);
175 ((JComboBox) value_control).setSelectedItem(existing_value);
176 }
177 }
178 else {
179 String default_value = argument.getDefaultValue();
180 if (default_value != null) {
181 // if no namespace for default value, add ex.
182 // won't work if we want to set a non-metadata value
183 if (MetadataTools.getMetadataSetNamespace(default_value).equals("")) {
184 default_value = StaticStrings.EXTRACTED_NAMESPACE+default_value;
185 }
186 selectValue((JComboBox) value_control, default_value);
187 }
188 }
189 break;
190
191 case Argument.METADATA_SET_NAMESPACE:
192 value_control = new JComboBox();
193 value_control.setComponentOrientation(Dictionary.getOrientation());
194 // !! Hack for exploding metadata databases: add the (empty) exploded metadata set
195 File exploded_metadata_set_file = new File(Gatherer.getGLIMetadataDirectoryPath() + "exp" + StaticStrings.METADATA_SET_EXTENSION);
196 MetadataSet exploded_metadata_set = new MetadataSet(exploded_metadata_set_file);
197 Gatherer.c_man.importMetadataSet(exploded_metadata_set);
198
199 // All the loaded metadata sets except the extracted metadata set are applicable
200 ArrayList metadata_sets = MetadataSetManager.getMetadataSets();
201 for (int i = metadata_sets.size() - 1; i >= 0; i--) {
202 MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
203 if (!(metadata_set.getNamespace().equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE))) {
204 ((JComboBox)value_control).addItem(metadata_set);
205 }
206 }
207
208 selectValue((JComboBox) value_control, initial_value);
209
210 } // end of switch
211
212 // Enable or disable as necessary.
213 if(argument.isRequired() || argument.isAssigned() || is_enabled) {
214 if (enabled != null) {
215 enabled.setSelected(true);
216 }
217 if(value_control != null) {
218 value_control.setOpaque(true);
219 value_control.setBackground(Color.white);
220 value_control.setEnabled(true);
221 if(value_control instanceof JSpinner) {
222 // Set enabled
223 JComponent c = ((JSpinner)value_control).getEditor();
224 if ( c instanceof JSpinner.DefaultEditor ) {
225 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
226 JFormattedTextField field = editor.getTextField();
227 field.setEditable(true);
228 field.setBackground(Color.white);
229 }
230 }
231 }
232 }
233 else {
234 if (enabled != null) {
235 enabled.setSelected(false);
236 }
237 if(value_control != null) {
238 value_control.setOpaque(true);
239 value_control.setBackground(Color.lightGray);
240 value_control.setEnabled(false);
241 if(value_control instanceof JSpinner) {
242 // Set enabled
243 JComponent c = ((JSpinner)value_control).getEditor();
244 if ( c instanceof JSpinner.DefaultEditor ) {
245 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
246 JFormattedTextField field = editor.getTextField();
247 field.setEditable(false);
248 field.setBackground(Color.lightGray);
249 }
250 }
251 }
252 }
253
254 // Listener
255 if(value_control != null) {
256 if (argument.getType() != Argument.ENUM && argument.getType() != Argument.ENUM_STRING) {
257 // enums have already set tooltips based on option value
258 value_control.setToolTipText(tip);
259 }
260 add(value_control, BorderLayout.CENTER);
261 if (!argument.isRequired()) {
262 enabled.addActionListener(new EnabledListener(value_control));
263 }
264 }
265 }
266
267 public Argument getArgument() {
268 return argument;
269 }
270
271 public String getArgumentName() {
272 return argument.getName();
273 }
274
275 public String getValue() {
276 if(value_control == null) {
277 return null;
278 }
279 if (value_control instanceof JSpinner) {
280 return ((JSpinner)value_control).getValue().toString();
281 }
282 if(value_control instanceof JComboBox) {
283 Object selected_item = ((JComboBox)value_control).getSelectedItem();
284 if (selected_item != null) {
285 if (argument.getType() == Argument.METADATA_SET_NAMESPACE) {
286 return ((MetadataSet) selected_item).getNamespace();
287 }
288 if (selected_item instanceof Argument.ArgumentOption) {
289 return ((Argument.ArgumentOption)selected_item).name;
290 }
291 if (selected_item instanceof MetadataElement) {
292 return ((MetadataElement) selected_item).getFullName();
293 }
294 return selected_item.toString();
295 }
296 return null;
297 }
298 if(value_control instanceof JTextField) {
299 return ((JTextField)value_control).getText();
300 }
301 return null;
302 }
303 /** Retrieve the control used for storing values.
304 * @return JComponent
305 */
306 public JComponent getValueControl() {
307 return value_control;
308 }
309
310 public boolean isEnabled() {
311 if (enabled == null) {
312 return true; // always enabled
313 }
314 return enabled.isSelected();
315 }
316
317
318 /** Identifies this control by returning the name of the Argument it is based on.
319 * @return The name of the Argument as a <strong>String</strong>.
320 * @see org.greenstone.gatherer.cdm.Argument
321 */
322 public String toString() {
323 return argument.getName();
324 }
325 /** Updates the enwrapped Argument using the values provided by the controls.
326 * @return <i>true</i> if the update was successful, <i>false</i> otherwise.
327 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.Argument.ArgumentOption
328 * @see org.greenstone.gatherer.cdm.Language
329 */
330 public boolean updateArgument() {
331 if(argument.isRequired() || enabled.isSelected() ) {
332 argument.setAssigned(false);
333 String result = null;
334 switch(argument.getType()) {
335 case Argument.ENUM:
336 Argument.ArgumentOption option = (Argument.ArgumentOption)((JComboBox)value_control).getSelectedItem();
337 // its impossible not to choose an entry
338 argument.setValue(option.name);
339 argument.setAssigned(true);
340 return true;
341 case Argument.ENUM_STRING:
342 Object new_value_raw = ((JComboBox)value_control).getSelectedItem();
343 if (new_value_raw instanceof Argument.ArgumentOption) {
344 argument.setValue(((Argument.ArgumentOption)new_value_raw).name);
345 } else {
346 // have entered a new string
347 String new_value = new_value_raw.toString();
348 if (new_value.length() > 0) {
349 argument.setValue(new_value);
350 }
351 else {
352 String args[] = new String[1];
353 args[0] = argument.getName();
354 if(argument.isRequired()) {
355 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
356 }
357 // They've left the field blank
358 else {
359 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
360 argument.setValue(null);
361 }
362 args = null;
363 return false;
364 }
365 }
366 argument.setAssigned(true);
367 return true;
368 case Argument.FLAG:
369 // Should have already been handled above.
370 argument.setAssigned(true);
371 return true;
372 case Argument.INTEGER:
373 result = ((JSpinner)value_control).getValue().toString();
374 if(result.length() > 0) {
375 // Test if the value entered is a valid int.
376 try {
377 int x = Integer.parseInt(result);
378 }
379 catch(NumberFormatException nfe) {
380 String args[] = new String[2];
381 args[0] = argument.getName();
382 args[1] = result;
383 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Bad_Integer", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
384 args = null;
385 return false;
386 }
387 argument.setValue(result);
388 }
389 else {
390 String args[] = new String[1];
391 args[0] = argument.getName();
392 if(argument.isRequired()) {
393 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
394 }
395 // They've left the field blank
396 else {
397 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
398 argument.setValue(null);
399 }
400 args = null;
401 return false;
402 }
403 argument.setAssigned(true);
404 return true;
405 case Argument.LANGUAGE:
406 String language = (((JComboBox)value_control).getSelectedItem()).toString();
407 argument.setValue(language);
408 // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
409 argument.setAssigned(true);
410 return true;
411 case Argument.METADATA:
412 String meta_value = (((JComboBox)value_control).getSelectedItem()).toString();
413 if(meta_value.length() > 0) {
414
415 argument.setValue(meta_value);
416 }
417 else {
418 String args[] = new String[1];
419 args[0] = argument.getName();
420 if(argument.isRequired()) {
421 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
422 }
423 // They've left the field blank
424 else {
425 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
426 argument.setValue(null);
427 }
428 args = null;
429 return false;
430 }
431
432 argument.setAssigned(true);
433 return true;
434 case Argument.REGEXP:
435 case Argument.STRING:
436 result = ((JTextField)value_control).getText();
437 if(result.length() > 0) {
438 argument.setValue(result);
439 }
440 else {
441 String args[] = new String[1];
442 args[0] = argument.getName();
443 if(argument.isRequired()) {
444 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
445 }
446 // They've left the field blank
447 else {
448 JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
449 argument.setValue(null);
450 }
451 args = null;
452 return false;
453 }
454 argument.setAssigned(true);
455 return true;
456 }
457 return false;
458 }
459 else {
460 argument.setAssigned(false);
461 return true;
462 }
463 }
464
465
466 public boolean updateArgument(boolean checkRequired) {
467
468
469 if (checkRequired){
470 return updateArgument();
471 }
472 else{
473 if (argument.getType() == Argument.STRING){
474 String result = ((JTextField)value_control).getText();
475
476 if(result.length() > 0) {
477 argument.setValue(result);
478 argument.setAssigned(true);
479 }
480 }
481 }
482
483 return true;
484
485 }
486
487
488
489 /** Method to ensure that a certain value is selected, if it exists within that combobox to begin with.
490 * @param combobox The <strong>JComboBox</strong> whose selection we are trying to preset.
491 * @param target The desired value of the selection as a <strong>String</strong>.
492 * @return true if the item was found and selected, false otherwise
493 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.Argument.ArgumentOption
494 */
495 public static boolean selectValue(JComboBox combobox, String target)
496 {
497 for (int i = 0; i < combobox.getItemCount(); i++) {
498 Object object = combobox.getItemAt(i);
499
500 if (object instanceof Argument.ArgumentOption) {
501 Argument.ArgumentOption opt = (Argument.ArgumentOption) object;
502 if (opt.name.startsWith(target)) {
503 combobox.setSelectedIndex(i);
504 combobox.setToolTipText(opt.getToolTip());
505 return true;
506 }
507 }
508 else if (object instanceof MetadataElement) {
509 if(((MetadataElement)object).getFullName().equals(target)) {
510 combobox.setSelectedIndex(i);
511 return true;
512 }
513 }
514 else if (object.toString().equals(target)) {
515 combobox.setSelectedIndex(i);
516 return true;
517 }
518 }
519
520 return false;
521 }
522
523
524 /** Forces the control into an 'enabled' mode. */
525 public void setEnabled() {
526 enabled.setSelected(true);
527 }
528 /** Explicitly sets the value of a JTextField type control to the given String.
529 * @param value_str The new value of the control as a <strong>String</strong>.
530 */
531 public void setValue(String value_str) {
532 ((JTextField)value_control).setText(value_str);
533 }
534
535 /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
536 private class EnabledListener
537 implements ActionListener {
538 /** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
539 private JComponent target = null;
540
541 /** Constructor. */
542 public EnabledListener(JComponent target) {
543 this.target = target;
544 }
545
546 /** 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.
547 * @param event An <strong>ActionEvent</strong> containing information about the click.
548 */
549 public void actionPerformed(ActionEvent event) {
550 if (this.target == null) {
551 return;
552 }
553 JCheckBox source = (JCheckBox)event.getSource();
554 if(source.isSelected()) {
555 target.setBackground(Color.white);
556 target.setEnabled(true);
557 }
558 else {
559 target.setBackground(Color.lightGray);
560 target.setEnabled(false);
561 }
562 // Special case of stupid JSpinners who don't let their backgrounds change properly.
563 if(target instanceof JSpinner) {
564 JSpinner spinner = (JSpinner) target;
565 JComponent c = spinner.getEditor();
566 if ( c instanceof JSpinner.DefaultEditor ) {
567 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
568 JFormattedTextField field = editor.getTextField();
569 field.setEditable(source.isSelected());
570 if(source.isSelected()) {
571 field.setBackground(Color.white);
572 }
573 else {
574 field.setBackground(Color.lightGray);
575 }
576 }
577 }
578 }
579 }
580
581
582 /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
583 private class ToolTipUpdater
584 implements ActionListener {
585 /** 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.
586 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
587 */
588 public void actionPerformed(ActionEvent event) {
589 JComboBox source = (JComboBox)event.getSource();
590 Object object = source.getSelectedItem();
591 if(object instanceof Argument.ArgumentOption) {
592 Argument.ArgumentOption opt = (Argument.ArgumentOption)object;
593 if(opt != null) {
594 source.setToolTipText(opt.getToolTip());
595 }
596 else {
597 source.setToolTipText(StaticStrings.EMPTY_STR);
598 }
599 }
600 }
601 }
602}
Note: See TracBrowser for help on using the repository browser.