/** *######################################################################### * * A component of the Gatherer application, part of the Greenstone digital * library suite from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * Author: John Thompson, Greenstone Digital Library, University of Waikato * * Copyright (C) 1999 New Zealand Digital Library Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *######################################################################## */ package org.greenstone.gatherer.cdm; /************************************************************************************** * Written: 01/05/02 * Revised: 16/08/02 Optimized and Commented. * 11/07/03 DOM support **************************************************************************************/ import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import java.util.jar.*; import javax.swing.*; import javax.swing.event.*; import org.apache.xerces.parsers.*; import org.greenstone.gatherer.Dictionary; import org.greenstone.gatherer.Gatherer; import org.greenstone.gatherer.cdm.Argument; import org.greenstone.gatherer.cdm.CollectionConfiguration; import org.greenstone.gatherer.cdm.CollectionDesignManager; import org.greenstone.gatherer.cdm.CommandTokenizer; import org.greenstone.gatherer.cdm.Control; import org.greenstone.gatherer.cdm.Classifier; import org.greenstone.gatherer.cdm.DOMProxyListModel; import org.greenstone.gatherer.file.FileNode; import org.greenstone.gatherer.gui.DoubleImageButton; import org.greenstone.gatherer.gui.GComboBox; import org.greenstone.gatherer.gui.GLIButton; import org.greenstone.gatherer.msm.MSMEvent; import org.greenstone.gatherer.msm.MSMListener; import org.greenstone.gatherer.msm.MSMUtils; import org.greenstone.gatherer.util.StaticStrings; import org.greenstone.gatherer.util.Utility; import org.w3c.dom.*; import org.xml.sax.*; /** This class is responsible for keeping track of all the classifiers assigned to this collection, and providing methods for adding and removing them. * @author John Thompson, Greenstone Digital Library, University of Waikato * @version 2.3 */ public class ClassifierManager extends DOMProxyListModel { /** The default size for a label. */ static final private Dimension LABEL_SIZE = new Dimension(140, 20); /** A list of known, but currently unassigned, classifiers. */ private ArrayList library = null; /** The controls for editing the contents of this manager. */ private Control controls = null; private DOMProxyListModel model; /** Constructor. * @see org.greenstone.gatherer.cdm.DynamicListModel * @see org.greenstone.gatherer.collection.CollectionManager * @see org.greenstone.gatherer.msm.MetadataSetManager * @see org.greenstone.gatherer.msm.MSMListener */ public ClassifierManager() { super(CollectionDesignManager.collect_config.getDocumentElement(), CollectionConfiguration.CLASSIFY_ELEMENT, new Classifier()); this.model = this; Gatherer.println("ClassifierManager: " + getSize() + " classifiers parsed."); // Reload/Create the library loadClassifiers(); saveClassifiers(); } /** Method to add a new classifier to library. * @param classifier The new Classifier. * @see org.greenstone.gatherer.cdm.DynamicListModel */ public void addClassifier(Classifier classifier) { if(!library.contains(classifier)) { library.add(classifier); } } /** Method to assign a classifier. * @param classifier The base Classifier to assign. * @see org.greenstone.gatherer.cdm.DynamicListModel */ public void assignClassifier(Classifier classifier) { if(!contains(classifier)) { Element element = classifier.getElement(); // Locate where we should insert this new classifier. Node target_node = CollectionConfiguration.findInsertionPoint(element); add(root, classifier, target_node); Gatherer.c_man.configurationChanged(); } } /** Destructor. * @see org.greenstone.gatherer.Gatherer * @see org.greenstone.gatherer.cdm.CollectionDesignManager * @see org.greenstone.gatherer.cdm.DynamicListModel */ public void destroy() { if(controls != null) { controls.destroy(); controls = null; } library.clear(); library = null; } public Classifier getBaseClassifier(String name) { int library_size = library.size(); for(int i = 0; i < library_size; i++) { Classifier classifier = (Classifier) library.get(i); if(classifier.getName().equals(name)) { return classifier; } } // No success. return null; } /** Method to retrieve the classifier with the given index. * @param index The index of the desired classifier as an int. * @return The requested Classifier or null if no such classifier exists. */ public Classifier getClassifier(int index) { if(0 <= index && index < getSize()) { return (Classifier) getElementAt(index); } return null; } /** Method to retrieve the control for this manager. * @return the Control for editing classifiers */ public Control getControls() { if(controls == null) { // Build controls this.controls = new ClassifierControl(); } return controls; } public ArrayList getHierarchyClassifiers() { ArrayList result = new ArrayList(); for(int i = 0; i < getSize(); i++) { Classifier classifier = (Classifier) getElementAt(i); if(classifier.getName().equalsIgnoreCase(StaticStrings.HIERARCHY_CLASSIFIER)) { result.add(classifier); } classifier = null; } return result; } /** Determine if the Phind classifier has been assigned. * @return true if it has, false otherwise */ public boolean isPhindClassifierAssigned() { for(int i = 0; i < getSize(); i++) { Classifier classifier = (Classifier) getElementAt(i); if(classifier.getName().equalsIgnoreCase(StaticStrings.PHIND_CLASSIFIER)) { return true; } classifier = null; } return false; } /** Method to move a classifier in the list order. * @param classifier the Classifier you want to move. * @param direction true to move the classifier up, false to move it down. * @param all true to move to move all the way, false for a single step. */ public void moveClassifier(Classifier classifier, boolean direction, boolean all) { if(getSize() < 2) { Gatherer.println("Not enough classifiers to allow moving."); return; } if(all) { // Move to top if(direction) { // Remove the moving classifier remove(classifier); // Retrieve the first classifier Classifier first_classifier = (Classifier) getElementAt(0); // Add the moving classifier before the first classifier addBefore(classifier, first_classifier); first_classifier = null; Gatherer.c_man.configurationChanged(); } else { // Remove the moving classifier remove(classifier); // And add after last classifier add(getSize(), classifier); } } else { // Try to move the classifier one step in the desired direction. int index = indexOf(classifier); ///ystem.err.println("Index of " + classifier + " = " + index); if(direction) { index--; if(index < 0) { String args[] = new String[2]; args[0] = Dictionary.get("CDM.ClassifierManager.Classifier"); args[1] = classifier.getName(); JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Top", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); return; } remove(classifier); add(index, classifier); Gatherer.c_man.configurationChanged(); } else { index++; if(index >= getSize()) { String args[] = new String[2]; args[0] = Dictionary.get("CDM.ClassifierManager.Classifier_Str"); args[1] = classifier.getName(); JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Bottom", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); return; } remove(classifier); add(index, classifier); Gatherer.c_man.configurationChanged(); } } } /** 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. * @param classifier The Classifier to remove * @see org.greenstone.gatherer.cdm.DynamicListModel */ public void removeClassifier(Classifier classifier) { remove(classifier); Gatherer.c_man.configurationChanged(); } /** Method to cache the current contents of library (known classifiers) to file. * @see org.greenstone.gatherer.util.Utility */ public void saveClassifiers() { try { FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "classifiers.dat"); ObjectOutputStream out = new ObjectOutputStream(file); out.writeObject(library); out.close(); } catch (Exception error) { } } private Object[] getAvailable() { ArrayList available = new ArrayList(); int library_size = library.size(); for(int i = 0; i < library_size; i++) { Classifier classifier = (Classifier) library.get(i); if(!classifier.isAbstract()) { available.add(classifier); } classifier = null; } return available.toArray(); } /** Method to extract just the classifiers name from a file object. * @param classifier The File which references a certain classifier. * @return A String containing just the classifiers name, without extension. */ private String getClassifierName(File classifier) { String name = classifier.getName(); if(name.indexOf(".") != -1) { name = name.substring(0, name.indexOf(".")); } return name; } /** Method to load the details of a single plug-in. * @param classifier The classifier File you wish to load. */ private void loadClassifier(File classifier) { ///ystem.err.println("Attempting to parse " + classifier.toString()); Document document = null; long start; long end; // Run classinfo on this classifier, and then send the results for parsing. try { String args[] = null; if(Utility.isWindows()) { args = new String[4]; if(Gatherer.config.perl_path != null) { args[0] = Gatherer.config.perl_path; } else { args[0] = "Perl.exe"; } args[1] = Gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "classinfo.pl"; args[2] = "-xml"; args[3] = getClassifierName(classifier); } else { args = new String[3]; args[0] = "classinfo.pl"; args[1] = "-xml"; args[2] = getClassifierName(classifier); } // Create the process. Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(args); BufferedReader error_in = new BufferedReader(new InputStreamReader(process.getErrorStream())); String line = ""; StringBuffer xml = new StringBuffer(""); boolean xml_content = false; while((line = error_in.readLine()) != null) { if(xml_content) { xml.append(line); xml.append("\n"); } else if(line.trim().startsWith("Node at the root of the DOM model. * @return A newly created Classifier based on the information parsed from the DOM model. * @see org.greenstone.gatherer.cdm.Argument */ private Classifier parseXML(Node root) { Classifier classifier = new Classifier(); String node_name = null; for(Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) { node_name = node.getNodeName(); if(node_name.equals("Name")) { String name = MSMUtils.getValue(node); // 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. Classifier existing = getBaseClassifier(name); if(existing != null) { return existing; } classifier.setName(name); } else if(node_name.equals("Desc")) { classifier.setDescription(MSMUtils.getValue(node)); } else if(node_name.equals(CollectionConfiguration.ABSTRACT_ELEMENT)) { classifier.setIsAbstract(MSMUtils.getValue(node).equalsIgnoreCase(CollectionConfiguration.YES_STR)); } // Parse the multitude of arguments. else if(node_name.equals("Arguments")) { for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) { node_name = arg.getNodeName(); // An option. if(node_name.equals("Option")) { Argument argument = new Argument(); // If its an option we parse the multitude of details an options might have. for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) { node_name = det.getNodeName(); if(node_name.equals("Name")) { argument.setName(MSMUtils.getValue(det)); } else if(node_name.equals("Desc")) { argument.setDescription(MSMUtils.getValue(det)); } else if(node_name.equals("Type")) { argument.setType(MSMUtils.getValue(det)); } else if(node_name.equals("Default")) { argument.setDefaultValue(MSMUtils.getValue(det)); } else if(node_name.equals("List")) { // Two final loops are required to parse lists. for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) { if(value.getNodeName().equals("Value")) { String key = null; String desc = ""; for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) { node_name = subvalue.getNodeName(); if(node_name.equals("Name")) { key = MSMUtils.getValue(subvalue); } else if(node_name.equals("Desc")) { desc = MSMUtils.getValue(subvalue); } } if(key != null) { argument.addOption(key, desc); } } } } else if(node_name.equals("Required")) { String v = MSMUtils.getValue(det); ///ystem.err.println("Required = " + v); if(v.equalsIgnoreCase("yes")) { ///ystem.err.println("Setting required to true."); argument.setRequired(true); } } else if(node_name.equals(StaticStrings.RANGE_ELEMENT)) { String range_raw = MSMUtils.getValue(det); int index = -1; if((index = range_raw.indexOf(StaticStrings.COMMA_CHARACTER)) != -1) { if(index > 0) { try { String first_number = range_raw.substring(0, index); argument.setMinimum(Integer.parseInt(first_number)); first_number = null; } catch(Exception exception) { } } if(index + 1 < range_raw.length()) { try { String second_number = range_raw.substring(index + 1); argument.setMaximum(Integer.parseInt(second_number)); second_number = null; } catch(Exception exception) { } } } // Else it wasn't a valid range anyway, so ignore it } } classifier.addArgument(argument); } // A super classifier class. else if(node_name.equals("ClassInfo")) { Classifier super_classifier = parseXML(arg); classifier.setSuper(super_classifier); } } } } if(classifier.getName() != null) { addClassifier(classifier); return classifier; } return null; } /** A class which provides controls for assigned and editing classifiers. */ private class ClassifierControl extends JPanel implements Control { /** A combobox containing all of the known classifiers, including those that may have already been assigned. */ private GComboBox classifier = null; /** Button for adding classifiers. */ private JButton add = null; /** Button for configuring the selected classifier. */ private JButton configure = null; //private JButton move_bottom_button; private JButton move_down_button; //private JButton move_top_button; private JButton move_up_button; /** Button to remove the selected classifier. */ private JButton remove = null; /** A list of assigned classifiers. */ private JList classifier_list = null; /** The text area containing instructions on the use of this control. */ private JTextArea instructions = null; /** Constructor. * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.AddListener * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.ConfigureListener * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.RemoveListener */ public ClassifierControl() { Collections.sort(library); // Create add = new GLIButton(); add.setMnemonic(KeyEvent.VK_A); Dictionary.registerBoth(add, "CDM.ClassifierManager.Add", "CDM.ClassifierManager.Add_Tooltip"); JPanel button_pane = new JPanel(); JPanel central_pane = new JPanel(); configure = new GLIButton(); configure.setEnabled(false); configure.setMnemonic(KeyEvent.VK_C); Dictionary.registerBoth(configure, "CDM.ClassifierManager.Configure", "CDM.ClassifierManager.Configure_Tooltip"); JPanel header_pane = new JPanel(); instructions = new JTextArea(); instructions.setEditable(false); instructions.setLineWrap(true); instructions.setRows(6); instructions.setWrapStyleWord(true); Dictionary.registerText(instructions, "CDM.ClassifierManager.Instructions"); ClassifierComboboxListener ccl = new ClassifierComboboxListener(); classifier = new GComboBox(getAvailable()); classifier.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.editable_background", false)); classifier.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false)); classifier.setEditable(true); classifier.setTextNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_foreground", false)); classifier.setTextSelectionColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false)); if(classifier.getItemCount() > 0) { classifier.setSelectedIndex(0); ccl.itemStateChanged(new ItemEvent(classifier, 0, null, ItemEvent.SELECTED)); } JLabel classifier_label = new JLabel(); Dictionary.registerText(classifier_label, "CDM.ClassifierManager.Classifier"); classifier_list = new JList(model); classifier_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JLabel classifier_list_label = new JLabel(); classifier_list_label.setHorizontalAlignment(JLabel.CENTER); classifier_list_label.setOpaque(true); Dictionary.registerText(classifier_list_label, "CDM.ClassifierManager.Assigned"); JPanel classifier_list_pane = new JPanel(); JPanel classifier_pane = new JPanel(); remove = new GLIButton(); remove.setEnabled(false); remove.setMnemonic(KeyEvent.VK_R); Dictionary.registerBoth(remove, "CDM.ClassifierManager.Remove", "CDM.ClassifierManager.Remove_Tooltip"); JLabel title = new JLabel(); title.setHorizontalAlignment(JLabel.CENTER); title.setOpaque(true); Dictionary.registerText(title, "CDM.ClassifierManager.Title"); JPanel temp = new JPanel(new BorderLayout()); JPanel move_button_pane = new JPanel(); //move_top_button = new DoubleImageButton("", Utility.getImage("arrow-top.gif"), Utility.getImage("arrow-top-disabled.gif")); //move_top_button.setEnabled(false); //move_top_button.setMnemonic(KeyEvent.VK_T); // move_top_button.setDisplayedMnemonicIndex(8); // !! English-centric hack //move_top_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE); //Dictionary.registerBoth(move_top_button, "CDM.Move.Move_Top", "CDM.Move.Move_Top_Tooltip"); move_up_button = new DoubleImageButton("", Utility.getImage("arrow-up.gif"), Utility.getImage("arrow-up-disabled.gif")); move_up_button.setEnabled(false); move_up_button.setMnemonic(KeyEvent.VK_U); move_up_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE); Dictionary.registerBoth(move_up_button, "CDM.Move.Move_Up", "CDM.Move.Move_Up_Tooltip"); move_down_button = new DoubleImageButton("", Utility.getImage("arrow-down.gif"), Utility.getImage("arrow-down-disabled.gif")); move_down_button.setEnabled(false); move_down_button.setMnemonic(KeyEvent.VK_D); move_down_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE); Dictionary.registerBoth(move_down_button, "CDM.Move.Move_Down", "CDM.Move.Move_Down_Tooltip"); //move_bottom_button = new DoubleImageButton("", Utility.getImage("arrow-bottom.gif"), Utility.getImage("arrow-bottom-disabled.gif")); //move_bottom_button.setEnabled(false); //move_bottom_button.setMnemonic(KeyEvent.VK_B); //move_bottom_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE); //Dictionary.registerBoth(move_bottom_button, "CDM.Move.Move_Bottom", "CDM.Move.Move_Bottom_Tooltip"); // Listeners add.addActionListener(new AddListener()); classifier.addItemListener(ccl); configure.addActionListener(new ConfigureListener()); remove.addActionListener(new RemoveListener()); classifier_list.addMouseListener(new ClickListener()); classifier_list.addListSelectionListener(new ListListener()); ccl = null; MoveListener ml = new MoveListener(); //move_bottom_button.addActionListener(ml); move_down_button.addActionListener(ml); //move_top_button.addActionListener(ml); move_up_button.addActionListener(ml); // Layout title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0)); instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); header_pane.setLayout(new BorderLayout()); header_pane.add(title, BorderLayout.NORTH); header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); move_button_pane.setLayout(new GridLayout(4,1)); move_button_pane.add(move_up_button); move_button_pane.add(new JPanel()); move_button_pane.add(new JPanel()); move_button_pane.add(move_down_button); classifier_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2)); classifier_list_pane.setLayout(new BorderLayout()); classifier_list_pane.add(classifier_list_label, BorderLayout.NORTH); classifier_list_pane.add(new JScrollPane(classifier_list), BorderLayout.CENTER); classifier_list_pane.add(move_button_pane, BorderLayout.EAST); classifier_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); classifier_pane.setLayout(new GridLayout(1, 2)); classifier_pane.add(classifier_label); classifier_pane.add(classifier); button_pane.setLayout(new GridLayout(1, 3)); button_pane.add(add); button_pane.add(configure); button_pane.add(remove); // Scope these mad bordering skillz. 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)))); temp.add(classifier_pane, BorderLayout.NORTH); temp.add(button_pane, BorderLayout.SOUTH); central_pane.setLayout(new BorderLayout()); central_pane.add(classifier_list_pane, BorderLayout.CENTER); central_pane.add(temp, BorderLayout.SOUTH); setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); setLayout(new BorderLayout()); add(header_pane, BorderLayout.NORTH); add(central_pane, BorderLayout.CENTER); } /** Method which acts like a destructor, tidying up references to persistant objects. */ public void destroy() { add = null; classifier = null; classifier_list = null; configure = null; instructions = null; remove = null; } /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called. */ public void gainFocus() { if(instructions != null) { instructions.setCaretPosition(0); } } public void loseFocus() { } /** This class listens for actions upon the add button in the controls, and if detected calls the assignClassifier() method. */ private class AddListener implements ActionListener { /** 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. * @param event An ActionEvent containing information garnered from the control action. * @see org.greenstone.gatherer.Gatherer * @see org.greenstone.gatherer.cdm.ArgumentConfiguration * @see org.greenstone.gatherer.cdm.Classifier */ public void actionPerformed(ActionEvent event) { Object selected_object = classifier.getSelectedItem(); // If there is something in the combobox, but we haven't registered a selection, then add the object and select it! if(selected_object != null) { // Retrieve the base classifier Classifier base_classifier = getBaseClassifier(selected_object.toString()); // Create a new element in the DOM Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.CLASSIFY_ELEMENT); Classifier new_classifier = null; if(base_classifier != null) { Gatherer.println("Creating Classifier based on existing Classifer."); element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, base_classifier.getName()); new_classifier = new Classifier(element, base_classifier); } else { Gatherer.println("Creating new custom Classifier."); element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, selected_object.toString()); new_classifier = new Classifier(element, null); // Also we add the custom classifier name to the combobox for convienence. classifier.addItem(selected_object); } element = null; // Automatically chain to configuration. This ensures required arguments are filled out. ArgumentConfiguration ac = new ArgumentConfiguration(new_classifier); if(ac.display()) { if(!model.contains(new_classifier)) { assignClassifier(new_classifier); classifier_list.setSelectedValue(new_classifier, true); } else { JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.ClassifierManager.Classifier_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } } ac = null; new_classifier = null; } } } /** This listener reacts to changes in the current selection of the classifier combobox. */ private class ClassifierComboboxListener implements ItemListener { /** When a user selects a certain plugin, update the tooltip to show the plugin description. */ public void itemStateChanged(ItemEvent event) { if(event.getStateChange() == ItemEvent.SELECTED) { // Retrieve the selected plugin Object current_selection = classifier.getSelectedItem(); // And reset the tooltip. If the plugin is null or is a string, then go back to the default message if(current_selection == null || current_selection instanceof String) { Dictionary.registerTooltip(classifier, "CDM.ClassifierManager.Classifier_Tooltip"); } else { Classifier current_classifier = (Classifier) current_selection; Dictionary.registerTooltip(classifier, Utility.formatHTMLWidth(current_classifier.getDescription(), 40), false); current_classifier = null; } current_selection = null; } } } /** Listens for double clicks apon the list and react as if the configure button was pushed. */ private class ClickListener extends MouseAdapter { /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt. * @param event A MouseEvent containing information about the mouse click. */ public void mouseClicked(MouseEvent event) { if(event.getClickCount() == 2 ) { if(!classifier_list.isSelectionEmpty()) { Classifier classifier = (Classifier) classifier_list.getSelectedValue(); ArgumentConfiguration ac = new ArgumentConfiguration(classifier); if(ac.display()) { refresh(classifier); } ac.destroy(); ac = null; } } } } /** 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. */ private class ConfigureListener implements ActionListener { /** 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. * @param event An ActionEvent containing information garnered from the control action. * @see org.greenstone.gatherer.cdm.ArgumentConfiguration * @see org.greenstone.gatherer.cdm.Classifier */ public void actionPerformed(ActionEvent event) { if(!classifier_list.isSelectionEmpty()) { Classifier classifier = (Classifier) classifier_list.getSelectedValue(); ArgumentConfiguration ac = new ArgumentConfiguration(classifier); if(ac.display()) { refresh(classifier); } ac.destroy(); ac = null; } } } /** 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 */ private class ListListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one ( the second one) if (classifier_list.isSelectionEmpty()) { //move_top_button.setEnabled(false); move_up_button.setEnabled(false); move_down_button.setEnabled(false); //move_bottom_button.setEnabled(false); configure.setEnabled(false); remove.setEnabled(false); } else { //move_top_button.setEnabled(true); move_up_button.setEnabled(true); move_down_button.setEnabled(true); //move_bottom_button.setEnabled(true); configure.setEnabled(true); remove.setEnabled(true); } } } } /** Listens for actions apon the move buttons in the manager controls, and if detected calls the moveClassifier() method of the manager with the appropriate details. */ private class MoveListener implements ActionListener { /** 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. * @param event An ActionEvent containing information garnered from the control action. */ public void actionPerformed(ActionEvent event) { if(!classifier_list.isSelectionEmpty()) { Object object = classifier_list.getSelectedValue(); if(object instanceof Classifier) { Classifier classifier = (Classifier) object; //if(event.getSource() == move_top_button) { // moveClassifier(classifier, true, true); //} //else if(event.getSource() == move_up_button) { moveClassifier(classifier, true, false); } else if(event.getSource() == move_down_button) { moveClassifier(classifier, false, false); } //else { // moveClassifier(classifier, false, true); //} classifier_list.setSelectedValue(classifier, true); } } } } /** This class listens for actions upon the remove button in the controls, and if detected calls the removeClassifier() method. */ private class RemoveListener implements ActionListener { /** 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 we can remove the selected Classifier. * @param event An ActionEvent containing information garnered from the control action. * @see org.greenstone.gatherer.cdm.Classifier */ public void actionPerformed(ActionEvent event) { if(!classifier_list.isSelectionEmpty()) { Object [] objects = classifier_list.getSelectedValues(); for(int i = 0; i < objects.length; i++) { if(objects[i] instanceof Classifier) { removeClassifier((Classifier)objects[i]); } } } } } } }