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

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

set the ComponentOrientation for a few things, for RTL gli

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