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

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

Changed plugin and classifiers tooltips to use the new registerTooltipText function.

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