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

Last change on this file since 7326 was 7241, checked in by kjdon, 20 years ago

moved the custom arguments panel to teh end of teh scrolling args

  • Property svn:keywords set to Author Date Id Revision
File size: 40.4 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 value = new GComboBox(Gatherer.c_man.getCollection().msm.getAssignedElements(), false);
449 //((JComboBox)value).setEditable(false);
450 //((JComboBox)value).setEditable(true);
451 // Now ensure we have the existing value or default value selected if either exist.
452 if(existing_value != null && existing_value.length() > 0) {
453 boolean found = selectValue((JComboBox)value, existing_value);
454 // Its possible that this is a custom value and so doesn't exist in the combobox. If so add it and then select it
455 if(!found) {
456 ((JComboBox)value).addItem(existing_value);
457 ((JComboBox)value).setSelectedItem(existing_value);
458 }
459 }
460 else if(default_value != null) {
461 selectValue((JComboBox)value, default_value);
462 }
463 break;
464 case Argument.METADATA:
465 // Comma separated metadata values.
466 ArrayList values = argument.getValues();
467 value = new GComboBox(Gatherer.c_man.getCollection().msm.getAssignedElements(), false);
468 //((JComboBox)value).setEditable(false);
469 DefaultListModel model = new DefaultListModel();
470 list = new JList(model);
471 list.setVisibleRowCount(3);
472 for(int i = 0; i < values.size(); i++) {
473 model.addElement(values.get(i));
474 }
475
476 one = new GLIButton();
477 one.addActionListener(new AddListener((JComboBox)value, list));
478 one.setMnemonic(KeyEvent.VK_A);
479 Dictionary.setBoth(one, "CDM.ArgumentConfiguration.Add", "CDM.ArgumentConfiguration.Add_Tooltip");
480 two = new GLIButton();
481 two.addActionListener(new RemoveListener(list));
482 two.setMnemonic(KeyEvent.VK_R);
483 Dictionary.setBoth(two, "CDM.ArgumentConfiguration.Remove", "CDM.ArgumentConfiguration.Remove_Tooltip");
484
485 if(argument.getValues().size() > 0 || argument.isRequired()) {
486 enabled.setSelected(true);
487 list.setBackground(Color.white);
488 list.setEnabled(true);
489 one.setEnabled(true);
490 two.setEnabled(true);
491 value.setEnabled(true);
492 }
493 else {
494 enabled.setSelected(false);
495 list.setBackground(Color.lightGray);
496 list.setEnabled(false);
497 one.setEnabled(false);
498 two.setEnabled(false);
499 value.setEnabled(false);
500 }
501 break;
502 } // end of switch
503
504 // Enable or disable as necessary.
505 if(argument.isRequired() || argument.isAssigned()) {
506 enabled.setSelected(true);
507 if(value != null) {
508 value.setOpaque(true);
509 value.setBackground(Color.white);
510 value.setEnabled(true);
511 if(value instanceof JSpinner) {
512 // Set enabled
513 JComponent c = ((JSpinner)value).getEditor();
514 if ( c instanceof JSpinner.DefaultEditor ) {
515 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
516 JFormattedTextField field = editor.getTextField();
517 field.setEditable(true);
518 field.setBackground(Color.white);
519 }
520 }
521 }
522 }
523 else {
524 enabled.setSelected(false);
525 if(value != null) {
526 value.setOpaque(true);
527 value.setBackground(Color.lightGray);
528 value.setEnabled(false);
529 if(value instanceof JSpinner) {
530 // Set enabled
531 JComponent c = ((JSpinner)value).getEditor();
532 if ( c instanceof JSpinner.DefaultEditor ) {
533 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
534 JFormattedTextField field = editor.getTextField();
535 field.setEditable(false);
536 field.setBackground(Color.lightGray);
537 }
538 }
539 }
540 }
541 // Listener
542 if(value != null && !argument.isRequired()) {
543 enabled.addActionListener(new EnabledListener(one, two, list, value));
544 }
545 // Layout
546 if(list == null) {
547 enabled.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
548 inner_pane.setLayout(new BorderLayout());
549 if(argument.isRequired()) {
550 inner_pane.add(label, BorderLayout.WEST);
551 }
552 else {
553 inner_pane.add(enabled, BorderLayout.WEST);
554 }
555 if(value != null) {
556 inner_pane.add(value, BorderLayout.CENTER);
557 }
558 }
559 else {
560 JPanel control_pane = new JPanel(new GridLayout(2,1));
561 control_pane.add(enabled);
562 control_pane.add(value);
563 control_pane.setOpaque(false);
564
565 JPanel left_pane = new JPanel(new BorderLayout());
566 left_pane.add(control_pane, BorderLayout.CENTER);
567 left_pane.add(one, BorderLayout.SOUTH);
568 left_pane.setOpaque(false);
569
570 JPanel right_pane = new JPanel(new BorderLayout());
571 right_pane.add(new JScrollPane(list), BorderLayout.CENTER);
572 right_pane.add(two, BorderLayout.SOUTH);
573 right_pane.setOpaque(false);
574
575 inner_pane.setLayout(new GridLayout(1,2));
576 inner_pane.add(left_pane);
577 inner_pane.add(right_pane);
578 }
579 setLayout(new BorderLayout());
580 //add(owner_label, BorderLayout.NORTH);
581 add(inner_pane, BorderLayout.CENTER);
582 }
583
584 public Argument getArgument() {
585 return argument;
586 }
587
588 public Object getValue() {
589 if(value instanceof JComboBox) {
590 return ((JComboBox)value).getSelectedItem();
591 }
592 else if(value instanceof JTextField) {
593 return ((JTextField)value).getText();
594 }
595 return null;
596 }
597 /** Identifies this control by returning the name of the Argument it is based on.
598 * @return The name of the Argument as a <strong>String</strong>.
599 * @see org.greenstone.gatherer.cdm.Argument
600 */
601 public String toString() {
602 return argument.getName();
603 }
604 /** Updates the enwrapped Argument using the values provided by the controls.
605 * @return <i>true</i> if the update was successful, <i>false</i> otherwise.
606 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption
607 * @see org.greenstone.gatherer.cdm.Language
608 * @see org.greenstone.gatherer.msm.ElementWrapper
609 */
610 public boolean updateArgument() {
611 if(enabled.isSelected() || argument.isRequired()) {
612 argument.setAssigned(false);
613 String result = null;
614 switch(argument.getType()) {
615 case Argument.ENUM:
616 ListOption option = (ListOption)((JComboBox)value).getSelectedItem();
617 if(option != null && option.getValue().length() > 0) {
618 argument.setValue(option.getValue());
619 }
620 else {
621 String args[] = new String[1];
622 args[0] = argument.getName();
623 if(argument.isRequired()) {
624 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
625 }
626 // They've left the field blank
627 else {
628 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
629 argument.setValue(null);
630 }
631 args = null;
632 return false;
633 }
634 argument.setAssigned(true);
635 return true;
636 case Argument.FLAG:
637 // Should have already been handled above.
638 argument.setAssigned(true);
639 return true;
640 case Argument.INTEGER:
641 result = ((JSpinner)value).getValue().toString();
642 if(result.length() > 0) {
643 // Test if the value entered is a valid int.
644 try {
645 int x = Integer.parseInt(result);
646 }
647 catch(NumberFormatException nfe) {
648 String args[] = new String[2];
649 args[0] = argument.getName();
650 args[1] = result;
651 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Bad_Integer", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
652 args = null;
653 return false;
654 }
655 argument.setValue(result);
656 }
657 else {
658 String args[] = new String[1];
659 args[0] = argument.getName();
660 if(argument.isRequired()) {
661 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
662 }
663 // They've left the field blank
664 else {
665 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
666 argument.setValue(null);
667 }
668 args = null;
669 return false;
670 }
671 argument.setAssigned(true);
672 return true;
673 case Argument.LANGUAGE:
674 String language = (((JComboBox)value).getSelectedItem()).toString();
675 argument.setValue(language);
676 // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
677 argument.setAssigned(true);
678 return true;
679 case Argument.METADATUM:
680 Object new_value_raw = ((JComboBox)value).getSelectedItem();
681 if(new_value_raw instanceof ElementWrapper) {
682 // Element wrappers are guaranteed to be non-zero length
683 argument.setValue(((ElementWrapper)new_value_raw).getName());
684 }
685 else {
686 // But we have to be careful as an arbitary string object could be zero length
687 String new_value = new_value_raw.toString();
688 ///ystem.err.println("The current value is: " + new_value);
689 if(new_value.length() > 0) {
690 argument.setValue(new_value);
691 }
692 else {
693 String args[] = new String[1];
694 args[0] = argument.getName();
695 if(argument.isRequired()) {
696 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
697 }
698 // They've left the field blank
699 else {
700 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
701 argument.setValue(null);
702 }
703 args = null;
704 return false;
705 }
706 }
707 argument.setAssigned(true);
708 return true;
709 case Argument.HIERARCHY:
710 argument.setValue(((JComboBox)value).getSelectedItem().toString());
711 // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
712 argument.setAssigned(true);
713 return true;
714 case Argument.METADATA:
715 DefaultListModel model = (DefaultListModel)list.getModel();
716 ArrayList values = new ArrayList();
717 for(int i = 0; i < model.size(); i++) {
718 values.add(model.get(i));
719 }
720 argument.setValues(values);
721 argument.setAssigned(true);
722 return true;
723 case Argument.REGEXP:
724 case Argument.STRING:
725 result = ((JTextField)value).getText();
726 if(result.length() > 0) {
727 argument.setValue(result);
728 }
729 else {
730 String args[] = new String[1];
731 args[0] = argument.getName();
732 if(argument.isRequired()) {
733 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
734 }
735 // They've left the field blank
736 else {
737 JOptionPane.showMessageDialog(self, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
738 argument.setValue(null);
739 }
740 args = null;
741 return false;
742 }
743 argument.setAssigned(true);
744 return true;
745 }
746 return false;
747 }
748 else {
749 argument.setAssigned(false);
750 return true;
751 }
752 }
753 /** Method to ensure that a certain value is selected, if it exists within that combobox to begin with.
754 * @param combobox The <strong>JComboBox</strong> whose selection we are trying to preset.
755 * @param target The desired value of the selection as a <strong>String</strong>.
756 * @return true if the item was found and selected, false otherwise
757 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption
758 * @see org.greenstone.gatherer.msm.ElementWrapper
759 */
760 public boolean selectValue(JComboBox combobox, String target) {
761 ///ystem.err.println("Searching for the target string: " + target);
762 for(int i = 0; i < combobox.getItemCount(); i++) {
763 Object object = combobox.getItemAt(i);
764 if(object instanceof ListOption) {
765 ListOption lo = (ListOption) object;
766 ///ystem.err.print("/tChecking: " + lo.getValue() + "... ");
767 if(lo.getValue().startsWith(target)) {
768 ///ystem.err.println("Match!");
769 combobox.setSelectedIndex(i);
770 return true;
771 }
772 /*
773 else {
774 System.err.println("No Match.");
775 }
776 */
777 }
778 else if(object instanceof ElementWrapper) {
779 if(object.toString().equals(target)) {
780 combobox.setSelectedIndex(i);
781 return true;
782 }
783 }
784 }
785 return false;
786 }
787 /** Forces the control into an 'enabled' mode. */
788 public void setEnabled() {
789 enabled.setSelected(true);
790 }
791 /** Explicitly sets the value of a JTextField type control to the given String.
792 * @param value_str The new value of the control as a <strong>String</strong>.
793 */
794 public void setValue(String value_str) {
795 ((JTextField)value).setText(value_str);
796 }
797 /** Listener which adds entries to a list from a combobox when fired. */
798 private class AddListener
799 implements ActionListener {
800 /** The model behind the target list. */
801 private DefaultListModel model = null;
802 /** The source for data to be added to the list. */
803 private JComboBox source = null;
804 /** The list to add data to. */
805 private JList target = null;
806 /** Constructor.
807 * @param source A <strong>JComboBox</strong> which serves as the source for data.
808 * @param target A <strong>JList</strong> which serves as the target for data.
809 */
810 public AddListener(JComboBox source, JList target) {
811 this.model = (DefaultListModel) target.getModel();
812 this.source = source;
813 this.target = target;
814 }
815 /** When the add button is clicked, we attempt to add the selected metadata from the source into the target.
816 * @param event An <strong>ActionEvent</strong> containing information about the event.
817 * @see org.greenstone.gatherer.msm.ElementWrapper
818 */
819 public void actionPerformed(ActionEvent event) {
820 ElementWrapper element = (ElementWrapper) source.getSelectedItem();
821 String name = element.toString();
822 if(!model.contains(name)) {
823 boolean found = false;
824 int index = 0;
825 while(!found && index < model.size()) {
826 String sibling = (String) model.get(index);
827 if(name.compareTo(sibling) < 0) {
828 model.add(index, name);
829 found = true;
830 }
831 else {
832 index++;
833 }
834 }
835 if(!found) {
836 model.addElement(name);
837 }
838 }
839 }
840 }
841 /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
842 private class EnabledListener
843 implements ActionListener {
844 /** One of two possible buttons that might have their enabled state changed by this listener. */
845 private JButton one = null;
846 /** One of two possible buttons that might have their enabled state changed by this listener. */
847 private JButton two = null;
848 /** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
849 private JComponent target = null;
850 /** A list which might have its enabled state changed by this listener. */
851 private JList list = null;
852 /** Constructor.
853 * @param one A <strong>JButton</strong> whose enabled state is determined by the listener, or <i>null</i> if no button.
854 * @param two A <strong>JButton</strong> whose enabled state is determined by the listener, or <i>null</i> if no button.
855 * @param list A <strong>JList</strong> whose enabled state is determined by the listener, or <i>null</i> if no list.
856 * @param target A <strong>JComponent</strong> whose enabled state is determined by the listener, or <i>null</i> if no component.
857 */
858 public EnabledListener(JButton one, JButton two, JList list, JComponent target) {
859 this.list = list;
860 this.one = one;
861 this.target = target;
862 this.two = two;
863 }
864 /** 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.
865 * @param event An <strong>ActionEvent</strong> containing information about the click.
866 */
867 public void actionPerformed(ActionEvent event) {
868 JCheckBox source = (JCheckBox)event.getSource();
869 if(source.isSelected()) {
870 target.setBackground(Color.white);
871 target.setEnabled(true);
872 if(target instanceof JSpinner) {
873 // Set enabled
874 JComponent c = ((JSpinner)target).getEditor();
875 if ( c instanceof JSpinner.DefaultEditor ) {
876 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
877 JFormattedTextField field = editor.getTextField();
878 field.setEditable(true);
879 field.setBackground(Color.white);
880 }
881 }
882 if(one != null && two != null && list != null) {
883 one.setEnabled(true);
884 two.setEnabled(true);
885 list.setBackground(Color.white);
886 list.setEnabled(true);
887 }
888 }
889 else {
890 target.setBackground(Color.lightGray);
891 target.setEnabled(false);
892if(target instanceof JSpinner) {
893 // Set enabled
894 JComponent c = ((JSpinner)target).getEditor();
895 if ( c instanceof JSpinner.DefaultEditor ) {
896 JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
897 JFormattedTextField field = editor.getTextField();
898 field.setEditable(false);
899 field.setBackground(Color.lightGray);
900 }
901 }
902 if(one != null && two != null && list != null) {
903 one.setEnabled(false);
904 two.setEnabled(false);
905 list.setBackground(Color.lightGray);
906 list.setEnabled(false);
907 }
908 }
909 }
910 }
911 /** If a metadata element is selected that requires an hfile, then this listener defaults that hfile. */
912 private class HierarchyListener
913 implements ItemListener {
914 /** 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.
915 * @param event An <strong>ItemEvent</strong> containing information about the selection.
916 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl
917 * @see org.greenstone.gatherer.valuetree.GValueModel
918 */
919 public void itemStateChanged(ItemEvent event) {
920 // Determine if the selected element represents a hierarchy.
921 Object temp = ((JComboBox)value).getSelectedItem();
922 String filename = temp.toString();
923 // Search for a argument control called hfile and enable and set value.
924 for(int i = 0; i < central_pane.getComponentCount(); i++) {
925 Object object = central_pane.getComponent(i);
926 if(object instanceof ArgumentControl) {
927 ArgumentControl control = (ArgumentControl) object;
928 if(control.toString().equals("hfile")) {
929 control.setValue(filename + ".txt");
930 control.setEnabled(true);
931 }
932 }
933 }
934 }
935 }
936 /** 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. */
937 private class ListOption
938 implements Comparable {
939 /** The maximum length of this String version of this item. */
940 private int MAX_DESC = 65;
941 /** The description of the value for this item. */
942 private String description = null;
943 /** A cached value for the text value of this option, as it never changes after the first call to toString(). */
944 private String text = null;
945 /** The value for this item. */
946 private String value = null;
947 /** Constructor.
948 * @param value The value for this item as a <strong>String</strong>.
949 * @param description The description of the value as a <strong>String</strong>.
950 */
951 public ListOption(String value, String description) {
952 this.description = description;
953 this.value = value;
954 }
955 /** Compare two possible ListOption objects for ordering.
956 * @param object The <strong>Object</strong> to compare to.
957 * @return An <i>int</i> indicating order as explained in String.
958 * @see java.lang.String#compareTo
959 */
960 public int compareTo(Object object) {
961 return toString().compareTo(object.toString());
962 }
963 /** Tests two possible ListOption objects for equality. Uses the result from compareTo().
964 * @param object The <strong>Object</strong> which may be equal.
965 * @return <i>true</i> if the objects are equal, <i>false</i> otherwise.
966 */
967 public boolean equals(Object object) {
968 return (compareTo(object) == 0);
969 }
970 /** Retrieve the description of this list item.
971 * @return The description as a <strong>String</strong>.
972 */
973 public String getDesc() {
974 return description;
975 }
976 /** Retrieve the value of this list item.
977 * @return The value as a <strong>String</strong>.
978 */
979 public String getValue() {
980 return value;
981 }
982 /** Convert this object into a nice readable String.
983 * @return A <strong>String</strong> representing this object.
984 */
985 public String toString() {
986 if(text == null) {
987 if(description.length() >= MAX_DESC) {
988 text = value + StaticStrings.MINUS_CHARACTER + description.substring(0, MAX_DESC) + StaticStrings.TRUNCATED_STRING;
989 }
990 else {
991 text = value + StaticStrings.MINUS_CHARACTER + description;
992 }
993 }
994 return text;
995 }
996 }
997 /** Listener which removes entries from a list from a combobox when fired. */
998 private class RemoveListener
999 implements ActionListener {
1000 /** The model behind the target list. */
1001 private DefaultListModel model = null;
1002 /** The list to remove data from. */
1003 private JList target = null;
1004 /** Constructor.
1005 * @param target A <strong>JList</strong>.
1006 */
1007 public RemoveListener(JList target) {
1008 this.model = (DefaultListModel) target.getModel();
1009 this.target = target;
1010 }
1011 /** When the remove button is clicked, we attempt to remove the selected metadata from the target.
1012 * @param event An <strong>ActionEvent</strong> containing information about the event.
1013 */
1014 public void actionPerformed(ActionEvent event) {
1015 if(!target.isSelectionEmpty()) {
1016 int index = target.getSelectedIndex();
1017 model.remove(index);
1018 }
1019 }
1020 }
1021 /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
1022 private class ToolTipUpdater
1023 implements ActionListener {
1024 /** 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.
1025 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
1026 */
1027 public void actionPerformed(ActionEvent event) {
1028 JComboBox source = (JComboBox)event.getSource();
1029 Object object = source.getSelectedItem();
1030 if(object instanceof ListOption) {
1031 ListOption lo = (ListOption)object;
1032 if(lo != null) {
1033 String description = Utility.formatHTMLWidth(lo.getDesc(), 60);
1034 source.setToolTipText(description);
1035 }
1036 else {
1037 source.setToolTipText(StaticStrings.EMPTY_STR);
1038 }
1039 }
1040 }
1041 }
1042 }
1043}
Note: See TracBrowser for help on using the repository browser.