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

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

Removed all occurrences of classes explicitly importing other classes in the same package.

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