source: trunk/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java@ 5234

Last change on this file since 5234 was 5218, checked in by mdewsnip, 21 years ago

Changed "move to top/up/down/bottom" buttons to be DoubleImageButtons.

  • Property svn:keywords set to Author Date Id Revision
File size: 31.8 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/**************************************************************************************
29 * Written: 01/05/02
30 * Revised: 16/08/02 Optimized and Commented.
31 * 11/07/03 DOM support
32 **************************************************************************************/
33import java.awt.*;
34import java.awt.event.*;
35import java.io.*;
36import java.util.*;
37import java.util.jar.*;
38import javax.swing.*;
39import javax.swing.event.*;
40import org.apache.xerces.parsers.*;
41import org.greenstone.gatherer.Gatherer;
42import org.greenstone.gatherer.cdm.Argument;
43import org.greenstone.gatherer.cdm.CollectionConfiguration;
44import org.greenstone.gatherer.cdm.CollectionDesignManager;
45import org.greenstone.gatherer.cdm.CommandTokenizer;
46import org.greenstone.gatherer.cdm.Control;
47import org.greenstone.gatherer.cdm.Classifier;
48import org.greenstone.gatherer.cdm.DOMProxyListModel;
49import org.greenstone.gatherer.file.FileNode;
50import org.greenstone.gatherer.gui.DoubleImageButton;
51import org.greenstone.gatherer.gui.GComboBox;
52import org.greenstone.gatherer.msm.MSMEvent;
53import org.greenstone.gatherer.msm.MSMListener;
54import org.greenstone.gatherer.msm.MSMUtils;
55import org.greenstone.gatherer.util.Utility;
56import org.w3c.dom.*;
57import org.xml.sax.*;
58/** This class is responsible for keeping track of all the classifiers assigned to this collection, and providing methods for adding and removing them.
59 * @author John Thompson, Greenstone Digital Library, University of Waikato
60 * @version 2.3
61 */
62public class ClassifierManager
63 extends DOMProxyListModel {
64
65 /** The default size for a label. */
66 static final private Dimension LABEL_SIZE = new Dimension(140, 20);
67
68 /** A list of known, but currently unassigned, classifiers. */
69 private ArrayList library = null;
70 /** The controls for editing the contents of this manager. */
71 private Control controls = null;
72
73 private DOMProxyListModel model;
74
75 /** Constructor.
76 * @see org.greenstone.gatherer.cdm.DynamicListModel
77 * @see org.greenstone.gatherer.collection.CollectionManager
78 * @see org.greenstone.gatherer.msm.MetadataSetManager
79 * @see org.greenstone.gatherer.msm.MSMListener
80 */
81 public ClassifierManager() {
82 super(CollectionDesignManager.collect_config.getDocumentElement(), CollectionConfiguration.CLASSIFY_ELEMENT, new Classifier());
83 this.model = this;
84 Gatherer.println("ClassifierManager: " + getSize() + " classifiers parsed.");
85 // Reload/Create the library
86 loadClassifiers();
87 saveClassifiers();
88 }
89
90 /** Method to add a new classifier to library.
91 * @param classifier The new <strong>Classifier</strong>.
92 * @see org.greenstone.gatherer.cdm.DynamicListModel
93 */
94 public void addClassifier(Classifier classifier) {
95 if(!library.contains(classifier)) {
96 library.add(classifier);
97 }
98 }
99
100 /** Method to assign a classifier.
101 * @param classifier The base <strong>Classifier</strong> to assign.
102 * @see org.greenstone.gatherer.cdm.DynamicListModel
103 */
104 public void assignClassifier(Classifier classifier) {
105 if(!contains(classifier)) {
106 Element element = classifier.getElement();
107 // Locate where we should insert this new classifier.
108 Node target_node = CollectionConfiguration.findInsertionPoint(element);
109 add(root, classifier, target_node);
110 Gatherer.c_man.configurationChanged();
111 }
112 }
113
114 /** Destructor.
115 * @see org.greenstone.gatherer.Gatherer
116 * @see org.greenstone.gatherer.cdm.CollectionDesignManager
117 * @see org.greenstone.gatherer.cdm.DynamicListModel
118 */
119 public void destroy() {
120 if(controls != null) {
121 controls.destroy();
122 controls = null;
123 }
124 library.clear();
125 library = null;
126 }
127
128 public Classifier getBaseClassifier(String name) {
129 int library_size = library.size();
130 for(int i = 0; i < library_size; i++) {
131 Classifier classifier = (Classifier) library.get(i);
132 if(classifier.getName().equals(name)) {
133 return classifier;
134 }
135 }
136 // No success.
137 return null;
138 }
139
140 /** Method to retrieve the classifier with the given index.
141 * @param index The index of the desired classifier as an <i>int</i>.
142 * @return The requested Classifier or <i>null</i> if no such classifier exists.
143 */
144 public Classifier getClassifier(int index) {
145 if(0 <= index && index < getSize()) {
146 return (Classifier) getElementAt(index);
147 }
148 return null;
149 }
150
151 /** Method to retrieve the control for this manager.
152 * @return the Control for editing classifiers
153 */
154 public Control getControls() {
155 if(controls == null) {
156 // Build controls
157 this.controls = new ClassifierControl();
158 }
159 return controls;
160 }
161
162 /** Method to move a classifier in the list order.
163 * @param classifier the Classifier you want to move.
164 * @param direction true to move the classifier up, false to move it down.
165 * @param all true to move to move all the way, false for a single step.
166 */
167 public void moveClassifier(Classifier classifier, boolean direction, boolean all) {
168 if(getSize() < 2) {
169 Gatherer.println("Not enough classifiers to allow moving.");
170 return;
171 }
172 if(all) {
173 // Move to top
174 if(direction) {
175 // Remove the moving classifier
176 remove(classifier);
177 // Retrieve the first classifier
178 Classifier first_classifier = (Classifier) getElementAt(0);
179 // Add the moving classifier before the first classifier
180 addBefore(classifier, first_classifier);
181 first_classifier = null;
182 Gatherer.c_man.configurationChanged();
183 }
184 else {
185 // Remove the moving classifier
186 remove(classifier);
187 // And add after last classifier
188 add(getSize(), classifier);
189 }
190 }
191 else {
192 // Try to move the classifier one step in the desired direction.
193 int index = indexOf(classifier);
194 ///ystem.err.println("Index of " + classifier + " = " + index);
195 if(direction) {
196 index--;
197 if(index < 0) {
198 String args[] = new String[2];
199 args[0] = get("CDM.ClassifierManager.Classifier");
200 args[1] = classifier.getName();
201 JOptionPane.showMessageDialog(Gatherer.g_man, get("CDM.Move.At_Top", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
202 return;
203 }
204 remove(classifier);
205 add(index, classifier);
206 Gatherer.c_man.configurationChanged();
207 }
208 else {
209 index++;
210 if(index >= getSize()) {
211 String args[] = new String[2];
212 args[0] = get("CDM.ClassifierManager.Classifier_Str");
213 args[1] = classifier.getName();
214 JOptionPane.showMessageDialog(Gatherer.g_man, get("CDM.Move.At_Bottom", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
215 return;
216 }
217 remove(classifier);
218 add(index, classifier);
219 Gatherer.c_man.configurationChanged();
220 }
221 }
222 }
223
224 /** This method removes an assigned classifier. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a classifier from the library.
225 * @param classifier The Classifier to remove
226 * @see org.greenstone.gatherer.cdm.DynamicListModel
227 */
228 public void removeClassifier(Classifier classifier) {
229 remove(classifier);
230 Gatherer.c_man.configurationChanged();
231 }
232
233 /** Method to cache the current contents of library (known classifiers) to file.
234 * @see org.greenstone.gatherer.util.Utility
235 */
236 public void saveClassifiers() {
237 try {
238 FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "classifiers.dat");
239 ObjectOutputStream out = new ObjectOutputStream(file);
240 out.writeObject(library);
241 out.close();
242 }
243 catch (Exception error) {
244 }
245 }
246
247 /** Retrieve a phrase from the dictionary based on a certain key.
248 * @param key The search <strong>String</strong>.
249 * @return The matching phrase from the Dictionary.
250 */
251 private String get(String key) {
252 return get(key, (String[])null);
253 }
254 /** Retrieve a phrase from the dictionary based on a certain key and certain arguments.
255 * @param key The search <strong>String</strong>.
256 * @param args A <strong>String[]</strong> used to complete and format the returned phrase.
257 * @return The matching phrase from the Dictionary.
258 * @see org.greenstone.gatherer.Dictionary
259 * @see org.greenstone.gatherer.Gatherer
260 */
261 private String get(String key, String arg) {
262 String[] args = null;
263 if(arg != null) {
264 args = new String[1];
265 args[0] = arg;
266 }
267 return get(key, args);
268 }
269
270 private String get(String key, String[] args) {
271 if(key.indexOf(".") == -1) {
272 key = "CDM.ClassifierManager." + key;
273 }
274 return Gatherer.dictionary.get(key, args);
275 }
276
277 private Object[] getAvailable() {
278 ArrayList available = new ArrayList();
279 int library_size = library.size();
280 for(int i = 0; i < library_size; i++) {
281 Classifier classifier = (Classifier) library.get(i);
282 if(!classifier.isAbstract()) {
283 available.add(classifier);
284 }
285 classifier = null;
286 }
287 return available.toArray();
288 }
289
290 /** Method to extract just the classifiers name from a file object.
291 * @param classifier The <strong>File</strong> which references a certain classifier.
292 * @return A <strong>String</strong> containing just the classifiers name, without extension.
293 */
294 private String getClassifierName(File classifier) {
295 String name = classifier.getName();
296 if(name.indexOf(".") != -1) {
297 name = name.substring(0, name.indexOf("."));
298 }
299 return name;
300 }
301
302 /** Method to load the details of a single plug-in.
303 * @param classifier The classifier <strong>File</strong> you wish to load.
304 */
305 private void loadClassifier(File classifier) {
306 ///ystem.err.println("Attempting to parse " + classifier.toString());
307 Document document = null;
308 long start;
309 long end;
310 // Run classinfo on this classifier, and then send the results for parsing.
311 try {
312 String args[] = null;
313 if(Utility.isWindows()) {
314 args = new String[4];
315 if(Gatherer.config.perl_path != null) {
316 args[0] = Gatherer.config.perl_path;
317 }
318 else {
319 args[0] = "Perl.exe";
320 }
321 args[1] = Gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "classinfo.pl";
322 args[2] = "-xml";
323 args[3] = getClassifierName(classifier);
324 }
325 else {
326 args = new String[3];
327 args[0] = "classinfo.pl";
328 args[1] = "-xml";
329 args[2] = getClassifierName(classifier);
330 }
331
332 // Create the process.
333 Runtime runtime = Runtime.getRuntime();
334 Process process = runtime.exec(args);
335 BufferedReader error_in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
336 String line = "";
337 StringBuffer xml = new StringBuffer("");
338 boolean xml_content = false;
339 while((line = error_in.readLine()) != null) {
340 if(xml_content) {
341 xml.append(line);
342 xml.append("\n");
343 }
344 else if(line.trim().startsWith("<?xml")) {
345 xml_content = true;
346 xml.append(line);
347 xml.append("\n");
348 }
349 }
350 error_in = null;
351 process = null;
352 runtime = null;
353 // If something has gone horribly wrong then xml will be empty.
354 if(xml.length() != 0) {
355 // Then read the xml from the piped input stream.
356 InputSource source = new InputSource(new StringReader(xml.toString()));
357 DOMParser parser = new DOMParser();
358 parser.parse(source);
359 document = parser.getDocument();
360 parser = null;
361 source = null;
362 }
363 else {
364 String classifier_name = getClassifierName(classifier);
365 Gatherer.println("Zero length argument xml detected for: " + classifier_name);
366 JOptionPane.showMessageDialog(Gatherer.g_man, get("Classifier_XML_Parse_Failed", classifier_name), get("General.Error"), JOptionPane.ERROR_MESSAGE);
367 classifier_name = null;
368 }
369 }
370 catch (Exception error) {
371 error.printStackTrace();
372 ///ystem.err.println("Error: Cannot parse " + getClassifierName(classifier));
373 }
374 if(document != null) {
375 parseXML(document.getDocumentElement());
376 }
377 }
378
379 /** Method to initially load information from the standard plug-ins within the gsdl Perl library.
380 * @see org.greenstone.gatherer.util.Utility
381 */
382 private void loadClassifiers() {
383 // Attempt to restore the cached file.
384 try {
385 FileInputStream file = new FileInputStream(Utility.BASE_DIR + "classifiers.dat");
386 ObjectInputStream input = new ObjectInputStream(file);
387 library = (ArrayList) input.readObject();
388 }
389 catch (Exception error) {
390 }
391 if(library == null) {
392 library = new ArrayList();
393 // Retrieve the gsdl home directory...
394 String directory = Gatherer.config.gsdl_path;
395 directory = directory + "perllib" + File.separator + "classify" + File.separator;
396 File files[] = (new File(directory)).listFiles();
397 if(files != null) {
398 // Create a progress indicator.
399 ParsingProgress progress = new ParsingProgress(get("CDM.ClassifierManager.Parsing.Title"), get("CDM.ClassifierManager.Parsing.Message"), files.length);
400 for(int i = 0; i < files.length; i++) {
401 // We only want to check Perl Modules.
402 if(files[i].getName().endsWith(".pm")) {
403 loadClassifier(files[i]);
404 }
405 progress.inc();
406 }
407 progress.dispose();
408 progress.destroy();
409 progress = null;
410 }
411 }
412 }
413
414 /** Parses a DOM tree model turning it into a Classifier and its associated arguments.
415 * @param root The <strong>Node</strong> at the root of the DOM model.
416 * @return A newly created <strong>Classifier</strong> based on the information parsed from the DOM model.
417 * @see org.greenstone.gatherer.cdm.Argument
418 */
419 private Classifier parseXML(Node root) {
420 Classifier classifier = new Classifier();
421 String node_name = null;
422 for(Node node = root.getFirstChild(); node != null;
423 node = node.getNextSibling()) {
424 node_name = node.getNodeName();
425 if(node_name.equals("Name")) {
426 String name = MSMUtils.getValue(node);
427 // We can save ourselves some processing time if a classifier with this name already exists in our manager. If so retrieve it and return it.
428 Classifier existing = getBaseClassifier(name);
429 if(existing != null) {
430 return existing;
431 }
432 classifier.setName(name);
433 }
434 else if(node_name.equals("Desc")) {
435 classifier.setDescription(MSMUtils.getValue(node));
436 }
437 else if(node_name.equals(CollectionConfiguration.ABSTRACT_ELEMENT)) {
438 classifier.setIsAbstract(MSMUtils.getValue(node).equalsIgnoreCase(CollectionConfiguration.YES_STR));
439 }
440 // Parse the multitude of arguments.
441 else if(node_name.equals("Arguments")) {
442 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
443 node_name = arg.getNodeName();
444 // An option.
445 if(node_name.equals("Option")) {
446 Argument argument = new Argument();
447 // If its an option we parse the multitude of details an options might have.
448 for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) {
449 node_name = det.getNodeName();
450 if(node_name.equals("Name")) {
451 argument.setName(MSMUtils.getValue(det));
452 }
453 else if(node_name.equals("Desc")) {
454 argument.setDescription(MSMUtils.getValue(det));
455 }
456 else if(node_name.equals("Type")) {
457 argument.setType(MSMUtils.getValue(det));
458 }
459 else if(node_name.equals("Default")) {
460 argument.setDefaultValue(MSMUtils.getValue(det));
461 }
462 else if(node_name.equals("List")) {
463 // Two final loops are required to parse lists.
464 for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) {
465 if(value.getNodeName().equals("Value")) {
466 String key = null;
467 String desc = "";
468 for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) {
469 node_name = subvalue.getNodeName();
470 if(node_name.equals("Name")) {
471 key = MSMUtils.getValue(subvalue);
472 }
473 else if(node_name.equals("Desc")) {
474 desc = MSMUtils.getValue(subvalue);
475 }
476 }
477 if(key != null) {
478 argument.addOption(key, desc);
479 }
480 }
481 }
482 }
483 else if(node_name.equals("Required")) {
484 String v = MSMUtils.getValue(det);
485 ///ystem.err.println("Required = " + v);
486 if(v.equalsIgnoreCase("yes")) {
487 ///ystem.err.println("Setting required to true.");
488 argument.setRequired(true);
489 }
490 }
491 }
492 classifier.addArgument(argument);
493 }
494 // A super classifier class.
495 else if(node_name.equals("ClassInfo")) {
496 Classifier super_classifier = parseXML(arg);
497 classifier.setSuper(super_classifier);
498 }
499 }
500 }
501 }
502 if(classifier.getName() != null) {
503 addClassifier(classifier);
504 return classifier;
505 }
506 return null;
507 }
508 /** A class which provides controls for assigned and editing classifiers. */
509 private class ClassifierControl
510 extends JPanel
511 implements Control {
512 /** A combobox containing all of the known classifiers, including those that may have already been assigned. */
513 private GComboBox classifier = null;
514 /** Button for adding classifiers. */
515 private JButton add = null;
516 /** Button for configuring the selected classifier. */
517 private JButton configure = null;
518
519 private JButton move_bottom_button;
520
521 private JButton move_down_button;
522
523 private JButton move_top_button;
524
525 private JButton move_up_button;
526
527 /** Button to remove the selected classifier. */
528 private JButton remove = null;
529
530 /** A list of assigned classifiers. */
531 private JList classifier_list = null;
532 /** The text area containing instructions on the use of this control. */
533 private JTextArea instructions = null;
534 /** Constructor.
535 * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.AddListener
536 * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.ConfigureListener
537 * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.RemoveListener
538 */
539 public ClassifierControl() {
540 Collections.sort(library);
541 // Create
542 add = new JButton(get("Add"));
543 JPanel button_pane = new JPanel();
544 JPanel central_pane = new JPanel();
545 configure = new JButton(get("Configure"));
546 configure.setEnabled(false);
547 JPanel header_pane = new JPanel();
548 instructions = new JTextArea(get("Instructions"));
549 instructions.setEditable(false);
550 instructions.setLineWrap(true);
551 instructions.setRows(6);
552 instructions.setWrapStyleWord(true);
553
554 classifier = new GComboBox(getAvailable());
555 classifier.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.editable_background", false));
556 classifier.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
557 classifier.setEditable(true);
558 classifier.setSelectedIndex(0);
559 classifier.setTextNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_foreground", false));
560 classifier.setTextSelectionColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
561
562 JLabel classifier_label = new JLabel(get("Classifier"));
563 classifier_list = new JList(model);
564 classifier_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
565 JLabel classifier_list_label = new JLabel(get("Assigned"));
566 classifier_list_label.setHorizontalAlignment(JLabel.CENTER);
567 classifier_list_label.setOpaque(true);
568 JPanel classifier_list_pane = new JPanel();
569 JPanel classifier_pane = new JPanel();
570 remove = new JButton(get("Remove"));
571 remove.setEnabled(false);
572 JLabel title = new JLabel(get("Title"));
573 title.setHorizontalAlignment(JLabel.CENTER);
574 title.setOpaque(true);
575 JPanel temp = new JPanel(new BorderLayout());
576
577 JPanel move_button_pane = new JPanel();
578
579 move_top_button = new DoubleImageButton(get("CDM.Move.Move_Top"), Utility.getImage("arrow-top.gif"), Utility.getImage("arrow-top-disabled.gif"));
580 move_top_button.setEnabled(false);
581 move_top_button.setMnemonic(KeyEvent.VK_T);
582 move_top_button.setDisplayedMnemonicIndex(8); // !! English-centric hack
583 move_top_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
584
585 move_up_button = new DoubleImageButton(get("CDM.Move.Move_Up"), Utility.getImage("arrow-up.gif"), Utility.getImage("arrow-up-disabled.gif"));
586 move_up_button.setEnabled(false);
587 move_up_button.setMnemonic(KeyEvent.VK_U);
588 move_up_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
589
590 move_down_button = new DoubleImageButton(get("CDM.Move.Move_Down"), Utility.getImage("arrow-down.gif"), Utility.getImage("arrow-down-disabled.gif"));
591 move_down_button.setEnabled(false);
592 move_down_button.setMnemonic(KeyEvent.VK_D);
593 move_down_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
594
595 move_bottom_button = new DoubleImageButton(get("CDM.Move.Move_Bottom"), Utility.getImage("arrow-bottom.gif"), Utility.getImage("arrow-bottom-disabled.gif"));
596 move_bottom_button.setEnabled(false);
597 move_bottom_button.setMnemonic(KeyEvent.VK_B);
598 move_bottom_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
599
600 // Listeners
601 add.addActionListener(new AddListener());
602 configure.addActionListener(new ConfigureListener());
603 remove.addActionListener(new RemoveListener());
604 classifier_list.addMouseListener(new ClickListener());
605 classifier_list.addListSelectionListener(new ListListener());
606
607 MoveListener ml = new MoveListener();
608 move_bottom_button.addActionListener(ml);
609 move_down_button.addActionListener(ml);
610 move_top_button.addActionListener(ml);
611 move_up_button.addActionListener(ml);
612 // Layout
613 title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
614
615 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
616
617 header_pane.setLayout(new BorderLayout());
618 header_pane.add(title, BorderLayout.NORTH);
619 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
620
621 move_button_pane.setLayout(new GridLayout(4,1));
622 move_button_pane.add(move_top_button);
623 move_button_pane.add(move_up_button);
624 move_button_pane.add(move_down_button);
625 move_button_pane.add(move_bottom_button);
626
627 classifier_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
628
629 classifier_list_pane.setLayout(new BorderLayout());
630 classifier_list_pane.add(classifier_list_label, BorderLayout.NORTH);
631 classifier_list_pane.add(new JScrollPane(classifier_list), BorderLayout.CENTER);
632 classifier_list_pane.add(move_button_pane, BorderLayout.EAST);
633
634 classifier_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
635
636 classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
637 classifier_pane.setLayout(new GridLayout(1, 2));
638 classifier_pane.add(classifier_label);
639 classifier_pane.add(classifier);
640
641 button_pane.setLayout(new GridLayout(1, 3));
642 button_pane.add(add);
643 button_pane.add(configure);
644 button_pane.add(remove);
645
646 // Scope these mad bordering skillz.
647 temp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,0,5,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Controls")), BorderFactory.createEmptyBorder(2,2,2,2))));
648 temp.add(classifier_pane, BorderLayout.NORTH);
649 temp.add(button_pane, BorderLayout.SOUTH);
650
651 central_pane.setLayout(new BorderLayout());
652 central_pane.add(classifier_list_pane, BorderLayout.CENTER);
653 central_pane.add(temp, BorderLayout.SOUTH);
654
655 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
656 setLayout(new BorderLayout());
657 add(header_pane, BorderLayout.NORTH);
658 add(central_pane, BorderLayout.CENTER);
659 }
660 /** Method which acts like a destructor, tidying up references to persistant objects.
661 */
662 public void destroy() {
663 add = null;
664 classifier = null;
665 classifier_list = null;
666 configure = null;
667 instructions = null;
668 remove = null;
669 }
670 /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
671 */
672 public void gainFocus() {
673 if(instructions != null) {
674 instructions.setCaretPosition(0);
675 }
676 }
677
678 public void loseFocus() {
679 }
680
681 /** This class listens for actions upon the add button in the controls, and if detected calls the assignClassifier() method.
682 */
683 private class AddListener
684 implements ActionListener {
685 /** Any implementation of ActionListener must include this method so that we can be informed when an action has occured on one of our target controls, so that we can add the selected Classifier.
686 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
687 * @see org.greenstone.gatherer.Gatherer
688 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
689 * @see org.greenstone.gatherer.cdm.Classifier
690 */
691 public void actionPerformed(ActionEvent event) {
692 Object selected_object = classifier.getSelectedItem();
693 // If there is something in the combobox, but we haven't registered a selection, then add the object and select it!
694 if(selected_object != null) {
695 // Retrieve the base classifier
696 Classifier base_classifier = getBaseClassifier(selected_object.toString());
697
698 // Create a new element in the DOM
699 Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.CLASSIFY_ELEMENT);
700 Classifier new_classifier = null;
701 if(base_classifier != null) {
702 Gatherer.println("Creating Classifier based on existing Classifer.");
703 element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, base_classifier.getName());
704 new_classifier = new Classifier(element, base_classifier);
705 }
706 else {
707 Gatherer.println("Creating new custom Classifier.");
708 element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, selected_object.toString());
709 new_classifier = new Classifier(element, null);
710 // Also we add the custom classifier name to the combobox for convienence.
711 classifier.addItem(selected_object);
712 }
713 element = null;
714 // Automatically chain to configuration. This ensures required arguments are filled out.
715 ArgumentConfiguration ac = new ArgumentConfiguration(new_classifier);
716 if(ac.display()) {
717 if(!model.contains(new_classifier)) {
718 assignClassifier(new_classifier);
719 classifier_list.setSelectedValue(new_classifier, true);
720 }
721 else {
722 JOptionPane.showMessageDialog(Gatherer.g_man, get("Classifier_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
723 }
724 }
725 ac = null;
726 new_classifier = null;
727 }
728 }
729 }
730 /** Listens for double clicks apon the list and react as if the configure button was pushed. */
731 private class ClickListener
732 extends MouseAdapter {
733 /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
734 * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
735 */
736 public void mouseClicked(MouseEvent event) {
737 if(event.getClickCount() == 2 ) {
738 if(!classifier_list.isSelectionEmpty()) {
739 Classifier classifier = (Classifier) classifier_list.getSelectedValue();
740 ArgumentConfiguration ac = new ArgumentConfiguration(classifier);
741 if(ac.display()) {
742 refresh(classifier);
743 }
744 ac.destroy();
745 ac = null;
746 }
747 }
748 }
749 }
750 /** This class listens for actions upon the configure button in the controls, and if detected creates a new ArgumentConfiguration dialog box to allow for configuration.
751 */
752 private class ConfigureListener
753 implements ActionListener {
754 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
755 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
756 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
757 * @see org.greenstone.gatherer.cdm.Classifier
758 */
759 public void actionPerformed(ActionEvent event) {
760 if(!classifier_list.isSelectionEmpty()) {
761 Classifier classifier = (Classifier) classifier_list.getSelectedValue();
762 ArgumentConfiguration ac = new ArgumentConfiguration(classifier);
763 if(ac.display()) {
764 refresh(classifier);
765 }
766 ac.destroy();
767 ac = null;
768 }
769 }
770 }
771
772 /** listens for changes in the list selection and enables the configure and remove buttons if there is a selection, disables them if there is no selection */
773 private class ListListener
774 implements ListSelectionListener {
775
776 public void valueChanged(ListSelectionEvent e) {
777 if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one ( the second one)
778 if (classifier_list.isSelectionEmpty()) {
779 move_top_button.setEnabled(false);
780 move_up_button.setEnabled(false);
781 move_down_button.setEnabled(false);
782 move_bottom_button.setEnabled(false);
783 configure.setEnabled(false);
784 remove.setEnabled(false);
785 }
786 else {
787 move_top_button.setEnabled(true);
788 move_up_button.setEnabled(true);
789 move_down_button.setEnabled(true);
790 move_bottom_button.setEnabled(true);
791 configure.setEnabled(true);
792 remove.setEnabled(true);
793 }
794 }
795 }
796 }
797
798 /** Listens for actions apon the move buttons in the manager controls, and if detected calls the <i>moveClassifier()</i> method of the manager with the appropriate details. */
799 private class MoveListener
800 implements ActionListener {
801 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
802 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
803 */
804 public void actionPerformed(ActionEvent event) {
805 if(!classifier_list.isSelectionEmpty()) {
806 Object object = classifier_list.getSelectedValue();
807 if(object instanceof Classifier) {
808 Classifier classifier = (Classifier) object;
809 if(event.getSource() == move_top_button) {
810 moveClassifier(classifier, true, true);
811 }
812 else if(event.getSource() == move_up_button) {
813 moveClassifier(classifier, true, false);
814 }
815 else if(event.getSource() == move_down_button) {
816 moveClassifier(classifier, false, false);
817 }
818 else {
819 moveClassifier(classifier, false, true);
820 }
821 classifier_list.setSelectedValue(classifier, true);
822 }
823 }
824 }
825 }
826
827 /** This class listens for actions upon the remove button in the controls, and if detected calls the removeClassifier() method.
828 */
829 private class RemoveListener
830 implements ActionListener {
831 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls, so we can remove the selected Classifier.
832 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
833 * @see org.greenstone.gatherer.cdm.Classifier
834 */
835 public void actionPerformed(ActionEvent event) {
836 if(!classifier_list.isSelectionEmpty()) {
837 Object [] objects = classifier_list.getSelectedValues();
838 for(int i = 0; i < objects.length; i++) {
839 if(objects[i] instanceof Classifier) {
840 removeClassifier((Classifier)objects[i]);
841 }
842 }
843 }
844 }
845 }
846 }
847}
Note: See TracBrowser for help on using the repository browser.