source: trunk/gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java@ 7997

Last change on this file since 7997 was 7995, checked in by mdewsnip, 20 years ago

Removed a whole lot of references to the msm package, which is on its way out.

  • Property svn:keywords set to Author Date Id Revision
File size: 40.3 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 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29import java.awt.*;
30import java.awt.event.*;
31import java.util.*;
32import javax.swing.*;
33import org.greenstone.gatherer.Configuration;
34import org.greenstone.gatherer.Dictionary;
35import org.greenstone.gatherer.Gatherer;
36import org.greenstone.gatherer.cdm.Argument;
37import org.greenstone.gatherer.cdm.ArgumentContainer;
38import org.greenstone.gatherer.cdm.Classifier;
39import org.greenstone.gatherer.cdm.CollectionDesignManager;
40import org.greenstone.gatherer.cdm.PlugIn;
41import org.greenstone.gatherer.gui.GComboBox;
42import org.greenstone.gatherer.gui.GLIButton;
43import org.greenstone.gatherer.gui.ModalDialog;
44import org.greenstone.gatherer.gui.SimpleMenuBar;
45import org.greenstone.gatherer.msm.ElementWrapper;
46import org.greenstone.gatherer.util.StaticStrings;
47import org.greenstone.gatherer.util.Utility;
48import org.greenstone.gatherer.valuetree.GValueModel;
49
50/** This class provides us with a dialog box which allows us to edit the arguments of either a PlugIn or a Classifier.
51 * @author John Thompson, Greenstone Digital Library, University of Waikato
52 * @version 2.3
53 * @see org.greenstone.gatherer.cdm.Classifier
54 * @see org.greenstone.gatherer.cdm.PlugIn
55 */
56public class ArgumentConfiguration
57 extends ModalDialog
58 implements ActionListener {
59 /** The data whose arguments we are editing. */
60 private ArgumentContainer data = null;
61 /** Argument these argument controls coloured or uncoloured (alternates to indicate inheritance). */
62 private boolean coloured = false;
63 /** Whether we have successfully edited the arguments associated with the ArgumentContainer or if we have failed to enter required arguments and have instead cancelled (which would cause argument additions to roll back). */
64 private boolean success = false;
65 /** A button to cancel this dialog. */
66 private JButton cancel = null;
67 /** A button to accept the changes and close the dialog. */
68 private JButton ok = null;
69 /** A reference to the ourselves so our inner classes can dispose us like a dialog. */
70 private ArgumentConfiguration self = null;
71 /** The central pane where a list of known arguments is displayed. */
72 private JPanel central_pane = null;
73 /** The field for entering custom arguments. */
74 private JTextField custom = null;
75 /** The panel for the custom arguments */
76 private JPanel custom_pane = null;
77 /** The name of the owner of the last argument control. */
78 private String previous_owner = null;
79 /** The size used for an argument label. */
80 static final private Dimension LABEL_SIZE = new Dimension(225, 25);
81 /** Size of a list. */
82 static final private Dimension LIST_SIZE = new Dimension(380, 50);
83 /** The size used for the dialog. */
84 static final private Dimension SIZE = new Dimension(800, 425);
85
86 /** Constructor.
87 * @param data The plugin or classifier whose arguments we are configuring, in the form of its supported <strong>ArgumentContainer</strong> interface.
88 * @see org.greenstone.gatherer.Configuration
89 */
90 public ArgumentConfiguration(ArgumentContainer data) {
91 super(Gatherer.g_man);
92 this.data = data;
93 this.self = this;
94
95 // Create
96 setModal(true);
97 setSize(SIZE);
98 setJMenuBar(new SimpleMenuBar("designingacollection")); // can we tell whether we are doing a classifier or plugin, to make the help more specific??
99 Dictionary.setText(this, "CDM.ArgumentConfiguration.Title");
100
101 central_pane = new JPanel();
102 JPanel content_pane = (JPanel) getContentPane();
103
104 custom_pane = new JPanel();
105 String custom_str = data.getCustom();
106 if (custom_str != null) {
107 custom = new JTextField(custom_str);
108 }
109 else {
110 custom = new JTextField();
111 }
112 JLabel custom_label = new JLabel();
113 custom_label.setPreferredSize(LABEL_SIZE);
114 Dictionary.setText(custom_label, "CDM.ArgumentConfiguration.Custom");
115
116 JPanel header_pane = new JPanel();
117 JLabel header = new JLabel();
118 header.setHorizontalAlignment(JLabel.CENTER);
119 header.setOpaque(true);
120 String args[] = new String[1];
121 args[0] = data.getName();
122 Dictionary.setText(header, "CDM.ArgumentConfiguration.Header", args);
123
124 JPanel button_pane = new JPanel();
125 cancel = new GLIButton();
126 cancel.setMnemonic(KeyEvent.VK_C);
127 Dictionary.setBoth(cancel, "General.Cancel", "General.Pure_Cancel_Tooltip");
128 ok = new GLIButton();
129 ok.setMnemonic(KeyEvent.VK_O);
130 Dictionary.setBoth(ok, "General.OK", "General.OK_Tooltip");
131
132 // Listeners
133 cancel.addActionListener(this);
134 ok.addActionListener(this);
135
136 // Layout
137 custom_pane.setLayout(new BorderLayout());
138 custom_pane.add(custom_label, BorderLayout.WEST);
139 custom_pane.add(custom, BorderLayout.CENTER);
140
141 button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
142 button_pane.setLayout(new GridLayout(1,2));
143 button_pane.add(ok);
144 button_pane.add(cancel);
145
146 central_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
147 central_pane.setLayout(new BoxLayout(central_pane, BoxLayout.Y_AXIS));
148
149 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
150 content_pane.setLayout(new BorderLayout());
151 content_pane.add(header, BorderLayout.NORTH);
152 content_pane.add(new JScrollPane(central_pane), BorderLayout.CENTER);
153 content_pane.add(button_pane, BorderLayout.SOUTH);
154
155 // Now generate a set of controls for each of the arguments.
156 generateControls();
157
158 // Display on screen.
159 Dimension screen_size = Gatherer.config.screen_size;
160 setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
161 screen_size = null;
162 }
163
164 /** Any implementation of ActionListener must include this method so that we can be informed when an action has occured on one of the controls we are listening to.
165 * @param event An <strong>ActionEvent</strong> containing pertinant information about the event that fired this call.
166 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl
167 * @see org.greenstone.gatherer.cdm.ArgumentContainer
168 */
169 public void actionPerformed(ActionEvent event) {
170 boolean cont = true;
171 if (event.getSource() == ok) {
172 // Clear the current focus to ensure components such as combobox have correctly updated
173 custom.requestFocus();
174 // Update the details stored in the data objects arguments.
175 data.setCustom(custom.getText());
176 // Loop through each of the controls in the central pane, updating the matching argument as necessary.
177 for(int i = 0; i < central_pane.getComponentCount(); i++) {
178 Component component = central_pane.getComponent(i);
179 if(component instanceof ArgumentControl) {
180 cont = cont && ((ArgumentControl)component).updateArgument();
181 }
182 }
183 if(cont) {
184 success = true;
185 }
186 }
187 if(cont) {
188 dispose();
189 }
190 }
191
192 /** Destructor. */
193 public void destroy() {
194 cancel = null;
195 central_pane = null;
196 custom_pane = null;
197 custom = null;
198 data = null;
199 ok = null;
200 self = null;
201 }
202
203 /** Method which actually forces the dialog to be shown on screen.
204 * @return <i>true</i> if the user completed configuration and pressed ok, <i>false</i> otherwise.
205 */
206 public boolean display() {
207 setVisible(true);
208 return success;
209 }
210
211 private void addHeader(String name, Color color) {
212 JPanel header = new JPanel();
213 header.setBackground(color);
214 JPanel inner_pane = new JPanel();
215 inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()));
216 inner_pane.setBackground(color);
217 JLabel header_label = new JLabel("<html><strong>" + name + "</strong></html>");
218 header_label.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
219 header_label.setHorizontalAlignment(JLabel.CENTER);
220 header_label.setOpaque(true);
221
222 // Layout
223 inner_pane.setLayout(new BorderLayout());
224 inner_pane.add(header_label, BorderLayout.CENTER);
225
226 header.setLayout(new BorderLayout());
227 header.add(inner_pane, BorderLayout.CENTER);
228 central_pane.add(header);
229 }
230
231 /** Method to iterate through the arguments associated with whatever argument container we are building an argument control view for, creating the appropriate controls for each.
232 * @see org.greenstone.gatherer.cdm.Argument
233 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl
234 */
235 private void generateControls() {
236 ArrayList arguments = data.getArguments(true, false);
237 int total_height = 250;
238 int mode = Gatherer.config.getMode();
239 for(int i = 0; i < arguments.size(); i++) {
240 Argument argument = (Argument) arguments.get(i);
241 if(mode > Configuration.LIBRARIAN_MODE || !(argument.getType() == Argument.REGEXP)) {
242 ArgumentControl argument_control = new ArgumentControl(argument);
243 total_height = total_height - argument_control.getPreferredSize().height;
244 central_pane.add(argument_control);
245 }
246 }
247 // now add in the custom args bit
248 coloured = !coloured;
249 Color color = (coloured ? Gatherer.config.getColor("coloring.collection_heading_background", false) : Gatherer.config.getColor("coloring.collection_tree_background", false));
250 addHeader(Dictionary.get("CDM.ArgumentConfiguration.Custom_Header"), color);
251 custom_pane.setBackground(color);
252 central_pane.add(custom_pane);
253 if(total_height > 0) {
254 JPanel filler = new JPanel();
255 filler.setPreferredSize(new Dimension(100, total_height));
256 filler.setSize(new Dimension(100, total_height));
257 central_pane.add(filler);
258 }
259 }
260
261 /** This class encapsulates all the technical difficulty of creating a specific control based on an Argument. */
262 private class ArgumentControl
263 extends JPanel {
264 /** The Argument this control will be based on. */
265 private Argument argument = null;
266
267 private Color colour_one = Gatherer.config.getColor("coloring.collection_heading_background", false);
268 private Color colour_two = Gatherer.config.getColor("coloring.collection_tree_background", false);
269 /** One of a possible two buttons available for adding to this control. */
270 private JButton one = null;
271 /** The second of two buttons available for adding to this control. */
272 private JButton two = null;
273 /** A checkbox to allow enabling or diabling of this Argument. */
274 private JCheckBox enabled = null;
275 /** Some form of editor component, such as a JComboBox or JTextField, used to set parameters to an Argument. */
276 private JComponent value = null;
277 /** Can be used in place of the other editor components if a list is required. */
278 private JList list = null;
279 /** Constructor.
280 * @param argument The <strong>Argument</strong> this control will be built around.
281 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.AddListener
282 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.EnabledListener
283 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.HierarchyListener
284 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption
285 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.RemoveListener
286 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ToolTipUpdater
287 */
288 public ArgumentControl(Argument argument) {
289 this.argument = argument;
290 ///ystem.err.println("generating controls for arg "+argument.getName());
291 String tip = "<html>" + argument.getDescription() + "</html>";
292 tip = Utility.formatHTMLWidth(tip, 60);
293
294 // If this is the first control, there is no history.
295 if(previous_owner == null) {
296 ///ystem.err.println("previous owner is null");
297 previous_owner = argument.getOwner();
298 addHeader(previous_owner, colour_two);
299 }
300 // Otherwise if the owner of the control has changed since the last argument, toggle the colouring of the control.
301 else if(previous_owner != argument.getOwner()) {
302 ///ystem.err.println("previous owner is different from current owner");
303 coloured = !coloured;
304 previous_owner = argument.getOwner();
305 addHeader(previous_owner, (coloured ? colour_one : colour_two));
306 }
307 // Create
308 if(coloured) {
309 setBackground(colour_one);
310 }
311 else {
312 setBackground(colour_two);
313 }
314 JLabel owner_label = new JLabel(argument.getOwner());
315 owner_label.setOpaque(false);
316 JLabel label = new JLabel(argument.getName());
317 label.setOpaque(false);
318 label.setPreferredSize(LABEL_SIZE);
319 label.setToolTipText(tip);
320 enabled = new JCheckBox(argument.getName());
321 enabled.setOpaque(false);
322 enabled.setPreferredSize(LABEL_SIZE);
323 enabled.setToolTipText(tip);
324 JPanel inner_pane = new JPanel();
325 inner_pane.setOpaque(false);
326 String existing_value = argument.getValue();
327 String default_value = argument.getDefaultValue();
328 switch(argument.getType()) {
329 case Argument.ENUM:
330 // Build an option model, wrapping each entry of the list table.
331 HashMap arg_list = argument.getOptions();
332 ArrayList options_model = new ArrayList();
333 Iterator it = arg_list.keySet().iterator();
334 while(it.hasNext()) {
335 String key = (String) it.next();
336 options_model.add(new ListOption(key, (String)arg_list.get(key)));
337 }
338 Collections.sort(options_model);
339 value = new GComboBox(options_model.toArray(), false);
340 //((JComboBox)value).setEditable(false);
341 ((JComboBox)value).addActionListener(new ToolTipUpdater());
342 if(existing_value != null && existing_value.length() > 0) {
343 // Select the correct value. Since they're all text strings we better iterate to be safe.
344 selectValue((JComboBox)value, existing_value);
345 }
346 else if(default_value != null) {
347 ///ystem.err.println("Default for argument: " + argument.getName());
348 // Same as above except for default value.
349 selectValue((JComboBox)value, default_value);
350 }
351 break;
352 case Argument.FLAG:
353 // Only need the check box.
354 break;
355 case Argument.HIERARCHY:
356 value = new GComboBox(Gatherer.c_man.getCollection().msm.getAssignedElements(true), false);
357 /** @TODO - figure out a smarter way of allowing Greenstone extracted metadata to be selected. */
358 //((JComboBox)value).setEditable(false);
359 ((JComboBox)value).addItemListener(new HierarchyListener());
360 // Now ensure we have the existing value or default value selected if either exist.
361 if(existing_value != null && existing_value.length() > 0) {
362 selectValue((JComboBox)value, existing_value);
363 }
364 else if(default_value != null) {
365 selectValue((JComboBox)value, default_value);
366 }
367 break;
368 case Argument.INTEGER:
369 // Build a spinner
370 int initial_value=0;
371 // If there was an original value, set it.
372 if(existing_value != null && !existing_value.equals("")) {
373 try {
374 initial_value = Integer.parseInt(existing_value);
375 //spinner.setValue(new Integer(existing_value));
376 }
377 catch (Exception error) {
378 Gatherer.println("ArgumentConfiguration Error: "+error);
379 }
380 } else if (default_value != null && !default_value.equals("")) {
381 try {
382 initial_value = Integer.parseInt(default_value);
383 //spinner.setValue(new Integer(default_value));
384 }
385 catch (Exception error) {
386 Gatherer.println("ArgumentConfiguration Error: "+error);
387 }
388 }
389 if (initial_value < argument.getMinimum()) {
390 initial_value = argument.getMinimum();
391 } else if (initial_value > argument.getMaximum()) {
392 initial_value = argument.getMaximum();
393 }
394
395 JSpinner spinner = new JSpinner(new SpinnerNumberModel(initial_value, argument.getMinimum(), argument.getMaximum(), 1));
396
397 // And remember it
398 value = spinner;
399 break;
400 case Argument.REGEXP:
401 case Argument.STRING:
402 // Use a standard text field
403 if(existing_value != null && existing_value.length() > 0) {
404 value = new JTextField(existing_value);
405 }
406 else {
407 if(default_value != null) {
408 value = new JTextField(default_value);
409 }
410 // Special test just for the hfile field.
411 else if(argument.getName().equals("hfile")) {
412 // Work through previous controls looking for the metadata one.
413 for(int i = 0; i < central_pane.getComponentCount(); i++) {
414 Object object = central_pane.getComponent(i);
415 if(object instanceof ArgumentControl) {
416 ArgumentControl control = (ArgumentControl) object;
417 if(control.toString().equals("metadata")) {
418 Object temp = control.getValue();
419 if(temp != null) {
420 value = new JTextField(temp.toString() + ".txt");
421 }
422 }
423
424 }
425 }
426 }
427 else {
428 value = new JTextField();
429 }
430 }
431 break;
432 case Argument.LANGUAGE:
433 value = new GComboBox(CollectionDesignManager.language_manager.getLanguageCodes().toArray(), false);
434 //((JComboBox)value).setEditable(false);
435 // Now ensure we have the existing value or default value selected if either exist.
436 Language selected = null;
437 if(existing_value != null && existing_value.length() > 0) {
438 selected = CollectionDesignManager.language_manager.getLanguage(existing_value);
439 }
440 else if(default_value != null) {
441 selected = CollectionDesignManager.language_manager.getLanguage(default_value);
442 }
443 if(selected != null) {
444 ((JComboBox)value).setSelectedItem(selected.getCode());
445 }
446 break;
447 case Argument.METADATUM:
448 case Argument.METADATA:
449 value = new GComboBox(Gatherer.c_man.getCollection().msm.getAssignedElements(), false);
450
451 // Editable for advanced modes (allows things like dc.Title,ex.Title)
452 if (Gatherer.config.getMode() > Configuration.ASSISTANT_MODE) {
453 ((JComboBox) value).setEditable(true);
454 }
455
456 // Now ensure we have the existing value or default value selected if either exist.
457 if(existing_value != null && existing_value.length() > 0) {
458 boolean found = selectValue((JComboBox)value, existing_value);
459 // Its possible that this is a custom value and so doesn't exist in the combobox. If so add it and then select it
460 if(!found) {
461 ((JComboBox)value).addItem(existing_value);
462 ((JComboBox)value).setSelectedItem(existing_value);
463 }
464 }
465 else if(default_value != null) {
466 selectValue((JComboBox)value, default_value);
467 }
468 break;
469// ---- Special interface for adding and ordering multiple metadata items ----
470// Turned off at Ian's request!
471// case Argument.METADATA:
472// // Comma separated metadata values.
473// ArrayList values = argument.getValues();
474// value = new GComboBox(Gatherer.c_man.getCollection().msm.getAssignedElements(), false);
475// //((JComboBox)value).setEditable(false);
476// DefaultListModel model = new DefaultListModel();
477// list = new JList(model);
478// list.setVisibleRowCount(3);
479// for(int i = 0; i < values.size(); i++) {
480// model.addElement(values.get(i));
481// }
482
483// one = new GLIButton();
484// one.addActionListener(new AddListener((JComboBox)value, list));
485// one.setMnemonic(KeyEvent.VK_A);
486// Dictionary.setBoth(one, "CDM.ArgumentConfiguration.Add", "CDM.ArgumentConfiguration.Add_Tooltip");
487// two = new GLIButton();
488// two.addActionListener(new RemoveListener(list));
489// two.setMnemonic(KeyEvent.VK_R);
490// Dictionary.setBoth(two, "CDM.ArgumentConfiguration.Remove", "CDM.ArgumentConfiguration.Remove_Tooltip");
491
492// if(argument.getValues().size() > 0 || argument.isRequired()) {
493// enabled.setSelected(true);
494// list.setBackground(Color.white);
495// list.setEnabled(true);
496// one.setEnabled(true);
497// two.setEnabled(true);
498// value.setEnabled(true);
499// }
500// else {
501// enabled.setSelected(false);
502// list.setBackground(Color.lightGray);
503// list.setEnabled(false);
504// one.setEnabled(false);
505// two.setEnabled(false);
506// value.setEnabled(false);
507// }
508// break;
509 } // end of switch
510
511 // Enable or disable as necessary.
512 if(argument.isRequired() || argument.isAssigned()) {
513 enabled.setSelected(true);
514 if(value != null) {
515 value.setOpaque(true);
516 value.setBackground(Color.white);
517 value.setEnabled(true);
518 if(value instanceof JSpinner) {
519 // Set enabled
520 JComponent c = ((JSpinner)value).getEditor();
521 if ( c instanceof JSpinner.DefaultEditor ) {
522 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
523 JFormattedTextField field = editor.getTextField();
524 field.setEditable(true);
525 field.setBackground(Color.white);
526 }
527 }
528 }
529 }
530 else {
531 enabled.setSelected(false);
532 if(value != null) {
533 value.setOpaque(true);
534 value.setBackground(Color.lightGray);
535 value.setEnabled(false);
536 if(value instanceof JSpinner) {
537 // Set enabled
538 JComponent c = ((JSpinner)value).getEditor();
539 if ( c instanceof JSpinner.DefaultEditor ) {
540 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
541 JFormattedTextField field = editor.getTextField();
542 field.setEditable(false);
543 field.setBackground(Color.lightGray);
544 }
545 }
546 }
547 }
548 // Listener
549 if(value != null && !argument.isRequired()) {
550 enabled.addActionListener(new EnabledListener(one, two, list, value));
551 }
552
553 // Layout
554 inner_pane.setLayout(new BorderLayout());
555 if (argument.isRequired()) {
556 inner_pane.add(label, BorderLayout.WEST);
557 }
558 else {
559 inner_pane.add(enabled, BorderLayout.WEST);
560 }
561
562 if (list == null) {
563 enabled.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
564 if (value != null) {
565 inner_pane.add(value, BorderLayout.CENTER);
566 }
567 }
568 else {
569 JPanel left_pane = new JPanel(new BorderLayout());
570 left_pane.add(new JLabel(""), BorderLayout.NORTH);
571 left_pane.add(value, BorderLayout.CENTER);
572 left_pane.add(one, BorderLayout.SOUTH);
573 left_pane.setOpaque(false);
574
575 JPanel right_pane = new JPanel(new BorderLayout());
576 right_pane.add(new JScrollPane(list), BorderLayout.CENTER);
577 right_pane.add(two, BorderLayout.SOUTH);
578 right_pane.setOpaque(false);
579
580 JPanel control_pane = new JPanel(new GridLayout(1, 2));
581 control_pane.add(left_pane);
582 control_pane.add(right_pane);
583
584 inner_pane.add(control_pane, BorderLayout.CENTER);
585 }
586
587 setLayout(new BorderLayout());
588 add(inner_pane, BorderLayout.CENTER);
589 }
590
591 public Argument getArgument() {
592 return argument;
593 }
594
595 public Object getValue() {
596 if(value instanceof JComboBox) {
597 return ((JComboBox)value).getSelectedItem();
598 }
599 else if(value instanceof JTextField) {
600 return ((JTextField)value).getText();
601 }
602 return null;
603 }
604 /** Identifies this control by returning the name of the Argument it is based on.
605 * @return The name of the Argument as a <strong>String</strong>.
606 * @see org.greenstone.gatherer.cdm.Argument
607 */
608 public String toString() {
609 return argument.getName();
610 }
611 /** Updates the enwrapped Argument using the values provided by the controls.
612 * @return <i>true</i> if the update was successful, <i>false</i> otherwise.
613 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption
614 * @see org.greenstone.gatherer.cdm.Language
615 */
616 public boolean updateArgument() {
617 if(enabled.isSelected() || argument.isRequired()) {
618 argument.setAssigned(false);
619 String result = null;
620 switch(argument.getType()) {
621 case Argument.ENUM:
622 ListOption option = (ListOption)((JComboBox)value).getSelectedItem();
623 if(option != null && option.getValue().length() > 0) {
624 argument.setValue(option.getValue());
625 }
626 else {
627 String args[] = new String[1];
628 args[0] = argument.getName();
629 if(argument.isRequired()) {
630 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
631 }
632 // They've left the field blank
633 else {
634 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
635 argument.setValue(null);
636 }
637 args = null;
638 return false;
639 }
640 argument.setAssigned(true);
641 return true;
642 case Argument.FLAG:
643 // Should have already been handled above.
644 argument.setAssigned(true);
645 return true;
646 case Argument.INTEGER:
647 result = ((JSpinner)value).getValue().toString();
648 if(result.length() > 0) {
649 // Test if the value entered is a valid int.
650 try {
651 int x = Integer.parseInt(result);
652 }
653 catch(NumberFormatException nfe) {
654 String args[] = new String[2];
655 args[0] = argument.getName();
656 args[1] = result;
657 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Bad_Integer", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
658 args = null;
659 return false;
660 }
661 argument.setValue(result);
662 }
663 else {
664 String args[] = new String[1];
665 args[0] = argument.getName();
666 if(argument.isRequired()) {
667 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
668 }
669 // They've left the field blank
670 else {
671 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
672 argument.setValue(null);
673 }
674 args = null;
675 return false;
676 }
677 argument.setAssigned(true);
678 return true;
679 case Argument.LANGUAGE:
680 String language = (((JComboBox)value).getSelectedItem()).toString();
681 argument.setValue(language);
682 // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
683 argument.setAssigned(true);
684 return true;
685 case Argument.METADATUM:
686 case Argument.METADATA:
687 Object new_value_raw = ((JComboBox)value).getSelectedItem();
688 if(new_value_raw instanceof ElementWrapper) {
689 // Element wrappers are guaranteed to be non-zero length
690 argument.setValue(((ElementWrapper)new_value_raw).getName());
691 }
692 else {
693 // But we have to be careful as an arbitary string object could be zero length
694 String new_value = new_value_raw.toString();
695 ///ystem.err.println("The current value is: " + new_value);
696 if(new_value.length() > 0) {
697 argument.setValue(new_value);
698 }
699 else {
700 String args[] = new String[1];
701 args[0] = argument.getName();
702 if(argument.isRequired()) {
703 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
704 }
705 // They've left the field blank
706 else {
707 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
708 argument.setValue(null);
709 }
710 args = null;
711 return false;
712 }
713 }
714 argument.setAssigned(true);
715 return true;
716// case Argument.METADATA:
717// DefaultListModel model = (DefaultListModel)list.getModel();
718// ArrayList values = new ArrayList();
719// for(int i = 0; i < model.size(); i++) {
720// values.add(model.get(i));
721// }
722// argument.setValues(values);
723// argument.setAssigned(true);
724// return true;
725 case Argument.HIERARCHY:
726 argument.setValue(((JComboBox)value).getSelectedItem().toString());
727 // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
728 argument.setAssigned(true);
729 return true;
730 case Argument.REGEXP:
731 case Argument.STRING:
732 result = ((JTextField)value).getText();
733 if(result.length() > 0) {
734 argument.setValue(result);
735 }
736 else {
737 String args[] = new String[1];
738 args[0] = argument.getName();
739 if(argument.isRequired()) {
740 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
741 }
742 // They've left the field blank
743 else {
744 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
745 argument.setValue(null);
746 }
747 args = null;
748 return false;
749 }
750 argument.setAssigned(true);
751 return true;
752 }
753 return false;
754 }
755 else {
756 argument.setAssigned(false);
757 return true;
758 }
759 }
760 /** Method to ensure that a certain value is selected, if it exists within that combobox to begin with.
761 * @param combobox The <strong>JComboBox</strong> whose selection we are trying to preset.
762 * @param target The desired value of the selection as a <strong>String</strong>.
763 * @return true if the item was found and selected, false otherwise
764 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption
765 */
766 public boolean selectValue(JComboBox combobox, String target) {
767 ///ystem.err.println("Searching for the target string: " + target);
768 for(int i = 0; i < combobox.getItemCount(); i++) {
769 Object object = combobox.getItemAt(i);
770 if(object instanceof ListOption) {
771 ListOption lo = (ListOption) object;
772 ///ystem.err.print("/tChecking: " + lo.getValue() + "... ");
773 if(lo.getValue().startsWith(target)) {
774 ///ystem.err.println("Match!");
775 combobox.setSelectedIndex(i);
776 return true;
777 }
778 /*
779 else {
780 System.err.println("No Match.");
781 }
782 */
783 }
784 else if(object instanceof ElementWrapper) {
785 if(object.toString().equals(target)) {
786 combobox.setSelectedIndex(i);
787 return true;
788 }
789 }
790 }
791 return false;
792 }
793 /** Forces the control into an 'enabled' mode. */
794 public void setEnabled() {
795 enabled.setSelected(true);
796 }
797 /** Explicitly sets the value of a JTextField type control to the given String.
798 * @param value_str The new value of the control as a <strong>String</strong>.
799 */
800 public void setValue(String value_str) {
801 ((JTextField)value).setText(value_str);
802 }
803 /** Listener which adds entries to a list from a combobox when fired. */
804 private class AddListener
805 implements ActionListener {
806 /** The model behind the target list. */
807 private DefaultListModel model = null;
808 /** The source for data to be added to the list. */
809 private JComboBox source = null;
810 /** The list to add data to. */
811 private JList target = null;
812 /** Constructor.
813 * @param source A <strong>JComboBox</strong> which serves as the source for data.
814 * @param target A <strong>JList</strong> which serves as the target for data.
815 */
816 public AddListener(JComboBox source, JList target) {
817 this.model = (DefaultListModel) target.getModel();
818 this.source = source;
819 this.target = target;
820 }
821 /** When the add button is clicked, we attempt to add the selected metadata from the source into the target.
822 * @param event An <strong>ActionEvent</strong> containing information about the event.
823 */
824 public void actionPerformed(ActionEvent event) {
825 ElementWrapper element = (ElementWrapper) source.getSelectedItem();
826 String name = element.toString();
827 if (!model.contains(name)) {
828 model.addElement(name);
829 }
830 }
831 }
832 /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
833 private class EnabledListener
834 implements ActionListener {
835 /** One of two possible buttons that might have their enabled state changed by this listener. */
836 private JButton one = null;
837 /** One of two possible buttons that might have their enabled state changed by this listener. */
838 private JButton two = null;
839 /** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
840 private JComponent target = null;
841 /** A list which might have its enabled state changed by this listener. */
842 private JList list = null;
843 /** Constructor.
844 * @param one A <strong>JButton</strong> whose enabled state is determined by the listener, or <i>null</i> if no button.
845 * @param two A <strong>JButton</strong> whose enabled state is determined by the listener, or <i>null</i> if no button.
846 * @param list A <strong>JList</strong> whose enabled state is determined by the listener, or <i>null</i> if no list.
847 * @param target A <strong>JComponent</strong> whose enabled state is determined by the listener, or <i>null</i> if no component.
848 */
849 public EnabledListener(JButton one, JButton two, JList list, JComponent target) {
850 this.list = list;
851 this.one = one;
852 this.target = target;
853 this.two = two;
854 }
855 /** 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.
856 * @param event An <strong>ActionEvent</strong> containing information about the click.
857 */
858 public void actionPerformed(ActionEvent event) {
859 JCheckBox source = (JCheckBox)event.getSource();
860 if(source.isSelected()) {
861 target.setBackground(Color.white);
862 target.setEnabled(true);
863 if(target instanceof JSpinner) {
864 // Set enabled
865 JComponent c = ((JSpinner)target).getEditor();
866 if ( c instanceof JSpinner.DefaultEditor ) {
867 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
868 JFormattedTextField field = editor.getTextField();
869 field.setEditable(true);
870 field.setBackground(Color.white);
871 }
872 }
873 if(one != null && two != null && list != null) {
874 one.setEnabled(true);
875 two.setEnabled(true);
876 list.setBackground(Color.white);
877 list.setEnabled(true);
878 }
879 }
880 else {
881 target.setBackground(Color.lightGray);
882 target.setEnabled(false);
883if(target instanceof JSpinner) {
884 // Set enabled
885 JComponent c = ((JSpinner)target).getEditor();
886 if ( c instanceof JSpinner.DefaultEditor ) {
887 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
888 JFormattedTextField field = editor.getTextField();
889 field.setEditable(false);
890 field.setBackground(Color.lightGray);
891 }
892 }
893 if(one != null && two != null && list != null) {
894 one.setEnabled(false);
895 two.setEnabled(false);
896 list.setBackground(Color.lightGray);
897 list.setEnabled(false);
898 }
899 }
900 }
901 }
902 /** If a metadata element is selected that requires an hfile, then this listener defaults that hfile. */
903 private class HierarchyListener
904 implements ItemListener {
905 /** Any implementation of ItemListener must include this method so that we can be informed when an item from the list is selected, and generate a predetermined hfile for that selection.
906 * @param event An <strong>ItemEvent</strong> containing information about the selection.
907 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl
908 * @see org.greenstone.gatherer.valuetree.GValueModel
909 */
910 public void itemStateChanged(ItemEvent event) {
911 // Determine if the selected element represents a hierarchy.
912 Object temp = ((JComboBox)value).getSelectedItem();
913 String filename = temp.toString();
914 // Search for a argument control called hfile and enable and set value.
915 for(int i = 0; i < central_pane.getComponentCount(); i++) {
916 Object object = central_pane.getComponent(i);
917 if(object instanceof ArgumentControl) {
918 ArgumentControl control = (ArgumentControl) object;
919 if(control.toString().equals("hfile")) {
920 control.setValue(filename + ".txt");
921 control.setEnabled(true);
922 }
923 }
924 }
925 }
926 }
927 /** 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. */
928 private class ListOption
929 implements Comparable {
930 /** The maximum length of this String version of this item. */
931 private int MAX_DESC = 65;
932 /** The description of the value for this item. */
933 private String description = null;
934 /** A cached value for the text value of this option, as it never changes after the first call to toString(). */
935 private String text = null;
936 /** The value for this item. */
937 private String value = null;
938 /** Constructor.
939 * @param value The value for this item as a <strong>String</strong>.
940 * @param description The description of the value as a <strong>String</strong>.
941 */
942 public ListOption(String value, String description) {
943 this.description = description;
944 this.value = value;
945 }
946 /** Compare two possible ListOption objects for ordering.
947 * @param object The <strong>Object</strong> to compare to.
948 * @return An <i>int</i> indicating order as explained in String.
949 * @see java.lang.String#compareTo
950 */
951 public int compareTo(Object object) {
952 return toString().compareTo(object.toString());
953 }
954 /** Tests two possible ListOption objects for equality. Uses the result from compareTo().
955 * @param object The <strong>Object</strong> which may be equal.
956 * @return <i>true</i> if the objects are equal, <i>false</i> otherwise.
957 */
958 public boolean equals(Object object) {
959 return (compareTo(object) == 0);
960 }
961 /** Retrieve the description of this list item.
962 * @return The description as a <strong>String</strong>.
963 */
964 public String getDesc() {
965 return description;
966 }
967 /** Retrieve the value of this list item.
968 * @return The value as a <strong>String</strong>.
969 */
970 public String getValue() {
971 return value;
972 }
973 /** Convert this object into a nice readable String.
974 * @return A <strong>String</strong> representing this object.
975 */
976 public String toString() {
977 if(text == null) {
978 if(description.length() >= MAX_DESC) {
979 text = value + StaticStrings.MINUS_CHARACTER + description.substring(0, MAX_DESC) + StaticStrings.TRUNCATED_STRING;
980 }
981 else {
982 text = value + StaticStrings.MINUS_CHARACTER + description;
983 }
984 }
985 return text;
986 }
987 }
988 /** Listener which removes entries from a list from a combobox when fired. */
989 private class RemoveListener
990 implements ActionListener {
991 /** The model behind the target list. */
992 private DefaultListModel model = null;
993 /** The list to remove data from. */
994 private JList target = null;
995 /** Constructor.
996 * @param target A <strong>JList</strong>.
997 */
998 public RemoveListener(JList target) {
999 this.model = (DefaultListModel) target.getModel();
1000 this.target = target;
1001 }
1002 /** When the remove button is clicked, we attempt to remove the selected metadata from the target.
1003 * @param event An <strong>ActionEvent</strong> containing information about the event.
1004 */
1005 public void actionPerformed(ActionEvent event) {
1006 if(!target.isSelectionEmpty()) {
1007 int index = target.getSelectedIndex();
1008 model.remove(index);
1009 }
1010 }
1011 }
1012 /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
1013 private class ToolTipUpdater
1014 implements ActionListener {
1015 /** 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.
1016 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
1017 */
1018 public void actionPerformed(ActionEvent event) {
1019 JComboBox source = (JComboBox)event.getSource();
1020 Object object = source.getSelectedItem();
1021 if(object instanceof ListOption) {
1022 ListOption lo = (ListOption)object;
1023 if(lo != null) {
1024 String description = Utility.formatHTMLWidth(lo.getDesc(), 60);
1025 source.setToolTipText(description);
1026 }
1027 else {
1028 source.setToolTipText(StaticStrings.EMPTY_STR);
1029 }
1030 }
1031 }
1032 }
1033 }
1034}
Note: See TracBrowser for help on using the repository browser.