/** *######################################################################### * * 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.msm; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import org.greenstone.gatherer.Dictionary; import org.greenstone.gatherer.Gatherer; import org.greenstone.gatherer.gui.ModalDialog; import org.greenstone.gatherer.gui.SimpleMenuBar; import org.greenstone.gatherer.msm.Declarations; import org.greenstone.gatherer.msm.MetadataSet; import org.greenstone.gatherer.msm.MetadataSetManager; import org.greenstone.gatherer.msm.MSMUtils; import org.greenstone.gatherer.util.ArrayTools; import org.w3c.dom.*; /** A class dedicated to producing the visual components used by the MSM package. * @author John Thompson, Greenstone Digital Library, University of Waikato * @version 1.2 */ public class MSMPrompt implements ActionListener { private boolean dialog_cancelled = false; private Dimension screen_size = null; private int action = Declarations.NO_ACTION; private JButton add = null; private JButton cancel = null; private JButton merge = null; private JButton rename = null; private JButton replace = null; private JButton skip = null; private JDialog on_screen = null; private JDialog dialog = null; private JProgressBar progress = null; private MetadataSetManager manager = null; private Object result = null; final static private Dimension MDE_SIZE = new Dimension(500,250); final static private Dimension MDS_SIZE = new Dimension(800,425); final static private Dimension PROGRESS_SIZE = new Dimension(500,105); final static private Dimension RENAME_LABEL_SIZE = new Dimension(100,25); final static private Dimension RENAME_SIZE = new Dimension(300,145); final static private Dimension SELECT_ELEMENT_SIZE = new Dimension(500,305); final static private Dimension SELECT_LABEL_SIZE = new Dimension(175, 25); final static private Dimension SELECT_SET_SIZE = new Dimension(600,210); final static private Dimension SELECT_SIZE = new Dimension(200,225); final static private int SELECT_LINE_COUNT = 8; public MSMPrompt(MetadataSetManager manager) { this.manager = manager; // Create components cancel = new JButton(); cancel.addActionListener(this); cancel.setEnabled(true); cancel.setMnemonic(KeyEvent.VK_C); Dictionary.registerBoth(cancel, "General.Cancel", "General.Cancel_Tooltip"); progress = new JProgressBar(); progress.setStringPainted(true); screen_size = Gatherer.config.screen_size; } /** When called this method produces a nice error message on the screen, advising the user that the add action has failed. * @param mde_new The Element that we were attempting to add. * @param reason The phrase key for the reason the add failed, as a String. */ public void addFailed(Element mde_new, String reason) { String args[] = new String[2]; args[0] = mde_new.getAttribute("name"); args[1] = Dictionary.get(reason); JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("MSMPrompt.Add_Failed", args), Dictionary.get("MSMPrompt.Add_Failed_Title"), JOptionPane.ERROR_MESSAGE); } /** Any implementation of ActionListener must include this method so that we can be informed when an action has occured. * @param event An ActionEvent containing information gatherer when this event occured. */ public void actionPerformed(ActionEvent event) { Object source = event.getSource(); action = Declarations.NO_ACTION; if (add != null && source == add) { action = Declarations.ADD; } else if (cancel != null && source == cancel) { action = Declarations.CANCEL; } else if (merge != null && source == merge) { action = Declarations.MERGE; } else if (rename != null && source == rename) { action = Declarations.RENAME; } else if (replace != null && source == replace) { action = Declarations.REPLACE; } else if (skip != null && source == skip) { action = Declarations.SKIP; } on_screen.setVisible(false); } /** Method called when the merging process is complete and the progress bar is no longer needed. */ public void endMerge() { } /** Method to indicate that yet another element has been succesfully merged, so that progress bar should reflect this. */ public void incrementMerge() { progress.setValue(progress.getValue() + 1); String percent = ((100 * progress.getValue()) / progress.getMaximum()) + "%"; progress.setString(percent); } /** Method to display the metadata element merging prompt, wherein the user determines how the attributes within an element should be merged. * @param mde_cur The current Element we are merging against. * @param atts_cur The list of matching attribute Elements of the current element in question. * @param mde_new The Element which we have choosen to merge in, and whose attributes are being examined. * @param att_new And the new elements attribute Element. * @return An object, which is either an Integer specifying what further action should be undertaken, if any, or if the action was replace, returns an Element, which is the attribute Element to replace with the new one */ public Object mDEPrompt(Element mde_cur, Element[] atts_cur, Element mde_new, Element att_new) { action = Declarations.NO_ACTION; // Construction and configuration JDialog dialog = new ModalDialog(Gatherer.g_man); dialog.setModal(true); dialog.setSize(MDE_SIZE); dialog.setJMenuBar(new SimpleMenuBar("importingpreviouslyassignedmetadata")); Dictionary.setText(dialog, "MSMPrompt.Merge_MDE"); JPanel content_pane = (JPanel)dialog.getContentPane(); JLabel element_name_label = new JLabel(); Dictionary.setText(element_name_label, "MSMPrompt.Element_Name"); JLabel element_name = new JLabel(MSMUtils.getFullName(mde_cur)); JLabel attribute_name_label = new JLabel(); Dictionary.setText(attribute_name_label, "MSMPrompt.Attribute"); JLabel attribute_name = new JLabel(att_new.getAttribute("name")); add = new JButton(); add.addActionListener(this); add.setEnabled(true); add.setMnemonic(KeyEvent.VK_A); Dictionary.registerBoth(add, "MSMPrompt.Add", "MSMPrompt.Add_Tooltip"); replace = new JButton(); replace.addActionListener(this); replace.setEnabled(false); replace.setMnemonic(KeyEvent.VK_R); Dictionary.registerBoth(replace, "MSMPrompt.Replace", "MSMPrompt.Replace_Tooltip"); skip = new JButton(); skip.addActionListener(this); skip.setEnabled(true); skip.setMnemonic(KeyEvent.VK_S); Dictionary.registerBoth(skip, "MSMPrompt.Skip", "MSMPrompt.Skip_Tooltip"); JList cur_values = new JList(atts_cur); cur_values.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); cur_values.setLayoutOrientation(JList.VERTICAL); cur_values.setVisibleRowCount(3); cur_values.setCellRenderer(new AttributeListCellRenderer()); cur_values.addListSelectionListener(new ElementListListener(cur_values, replace)); // Layout JPanel title_pane = new JPanel(); title_pane.setLayout(new GridLayout(2,2)); title_pane.add(element_name_label); title_pane.add(element_name); title_pane.add(attribute_name_label); title_pane.add(attribute_name); JPanel current_pane = new JPanel(); current_pane.setLayout(new BorderLayout()); current_pane.setBorder(BorderFactory.createTitledBorder(Dictionary.get("MSMPrompt.Current_Values"))); JScrollPane scroll = new JScrollPane(cur_values); current_pane.add(scroll, BorderLayout.CENTER); JPanel new_pane = new JPanel(); new_pane.setBorder(BorderFactory.createTitledBorder(Dictionary.get("MSMPrompt.New_Value"))); new_pane.setLayout(new BorderLayout()); JLabel new_att = new JLabel(MSMUtils.getValue(att_new)); new_pane.add(new_att, BorderLayout.WEST); JPanel central_pane = new JPanel(); central_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); central_pane.setLayout(new BoxLayout(central_pane, BoxLayout.Y_AXIS)); central_pane.add(title_pane); central_pane.add(current_pane); central_pane.add(new_pane); JPanel button_pane = new JPanel(); button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); button_pane.setLayout(new GridLayout(1,4)); button_pane.add(add); button_pane.add(replace); button_pane.add(skip); button_pane.add(cancel); content_pane.setLayout(new BorderLayout()); content_pane.add(central_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); // Display dialog.setLocation((screen_size.width - MDE_SIZE.width) / 2, (screen_size.height - MDE_SIZE.height) / 2); on_screen = dialog; on_screen.setVisible(true); // blocks until hidden on_screen.dispose(); // the return value - will either be an Integer containing the action, // of the selected Element for a replace Object result = new Integer(action); // need to get the value of the list selection if replace was clicked if (action == Declarations.REPLACE) { result = cur_values.getSelectedValue(); } content_pane = null; element_name_label = null; element_name = null; attribute_name_label = null; attribute_name=null; cur_values = null; title_pane=null; current_pane = null; scroll = null; new_pane = null; new_att = null; central_pane = null; button_pane = null; on_screen = null; dialog = null; return result; } /** This method displays the metadata data set merging prompt, wherein the user determines how the elements within a set should be merged. * @param mds_cur The current MetadataSet containing our document. * @param mde_cur The current Element we are merging against. * @param mds_new The MetadataSet we are merging in. * @param mde_new The Element which we have choosen to merge in. * @return An int specifying what further action should be undertaken, if any. */ public int mDSPrompt(MetadataSet mds_cur, Element mde_cur, MetadataSet mds_new, Element mde_new) { action = Declarations.NO_ACTION; // Construction and configuration JDialog dialog = new ModalDialog(Gatherer.g_man); dialog.setModal(true); dialog.setSize(MDS_SIZE); dialog.setJMenuBar(new SimpleMenuBar("importingpreviouslyassignedmetadata")); Dictionary.setText(dialog, "MSMPrompt.Merge_MDS"); JTextArea current_details = new JTextArea(); Dictionary.registerText(current_details, "MSMPrompt.No_Details"); JLabel current_details_label = new JLabel(); Dictionary.registerText(current_details_label, "MSMPrompt.Current_Details"); JTextArea new_details = new JTextArea(); Dictionary.registerText(new_details, "MSMPrompt.No_Details"); JLabel new_details_label = new JLabel(); Dictionary.registerText(new_details_label, "MSMPrompt.New_Details"); JLabel progress_label = new JLabel(); Dictionary.registerText(progress_label, "MSMPrompt.Progress"); add = new JButton(); add.addActionListener(this); add.setEnabled(false); add.setMnemonic(KeyEvent.VK_A); Dictionary.registerBoth(add, "MSMPrompt.Add", "MSMPrompt.Add_Tooltip"); merge = new JButton(); merge.addActionListener(this); merge.setEnabled(true); merge.setMnemonic(KeyEvent.VK_M); Dictionary.registerBoth(merge, "MSMPrompt.Merge", "MSMPrompt.Merge_Tooltip"); rename = new JButton(); rename.addActionListener(this); rename.setEnabled(false); rename.setMnemonic(KeyEvent.VK_N); Dictionary.registerBoth(rename, "MSMPrompt.Rename", "MSMPrompt.Rename_Tooltip"); replace = new JButton(); replace.addActionListener(this); replace.setEnabled(false); replace.setMnemonic(KeyEvent.VK_R); Dictionary.registerBoth(replace, "MSMPrompt.Replace", "MSMPrompt.Replace_Tooltip"); skip = new JButton(); skip.addActionListener(this); skip.setEnabled(true); skip.setMnemonic(KeyEvent.VK_S); Dictionary.registerBoth(skip, "MSMPrompt.Skip", "MSMPrompt.Skip_Tooltip"); JPanel content_pane = (JPanel)dialog.getContentPane(); if (mde_cur != null) { add.setEnabled(false); cancel.setEnabled(true); merge.setEnabled(true); rename.setEnabled(true); replace.setEnabled(true); skip.setEnabled(true); // Current details. String str_cur[] = MSMUtils.getStructuralDetails(mds_cur, mde_cur); String opt_cur[] = MSMUtils.getOptionListDetails(mde_cur); String ass_cur[] = MSMUtils.getAssignedValuesDetails(mds_cur, mde_cur); String details_cur = Dictionary.get("MSMPrompt.Structural", str_cur); if(opt_cur != null) { details_cur = details_cur + "\n" + Dictionary.get("MSMPrompt.OptionList", opt_cur); } if(ass_cur != null) { details_cur = details_cur + "\n" + Dictionary.get("MSMPrompt.AssignedValues", ass_cur); } current_details.setText(details_cur); str_cur = null; opt_cur = null; ass_cur = null; details_cur = null; } else { add.setEnabled(true); cancel.setEnabled(true); merge.setEnabled(true); rename.setEnabled(false); replace.setEnabled(false); skip.setEnabled(true); Dictionary.setText(current_details, "MSMPrompt.No_Element"); } // New details. String str_new[] = MSMUtils.getStructuralDetails(mds_new, mde_new); String opt_new[] = MSMUtils.getOptionListDetails(mde_new); String ass_new[] = MSMUtils.getAssignedValuesDetails(mds_new, mde_new); String details_new = Dictionary.get("MSMPrompt.Structural", str_new); if(opt_new != null) { details_new = details_new + "\n" + Dictionary.get("MSMPrompt.OptionList", opt_new); } if(ass_new != null) { details_new = details_new + "\n" + Dictionary.get("MSMPrompt.AssignedValues", ass_new); } new_details.setText(details_new); // Layout JPanel current_details_pane = new JPanel(); current_details_pane.setLayout(new BorderLayout()); current_details_pane.add(current_details_label, BorderLayout.NORTH); current_details_pane.add(new JScrollPane(current_details), BorderLayout.CENTER); JPanel new_details_pane = new JPanel(); new_details_pane.setLayout(new BorderLayout()); new_details_pane.add(new_details_label, BorderLayout.NORTH); new_details_pane.add(new JScrollPane(new_details), BorderLayout.CENTER); JPanel details_pane = new JPanel(); details_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); details_pane.setLayout(new GridLayout(1,2)); details_pane.add(current_details_pane); details_pane.add(new_details_pane); JPanel button_pane = new JPanel(); button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); button_pane.setLayout(new GridLayout(1,6)); button_pane.add(add); button_pane.add(merge); button_pane.add(rename); button_pane.add(replace); button_pane.add(skip); button_pane.add(cancel); JPanel control_pane = new JPanel(); control_pane.setLayout(new BorderLayout()); control_pane.add(details_pane, BorderLayout.CENTER); control_pane.add(button_pane, BorderLayout.SOUTH); JPanel progress_pane = new JPanel(); progress_pane.setBorder(BorderFactory.createEmptyBorder(5,5,0,5)); progress_pane.setLayout(new BorderLayout()); progress_pane.add(progress_label, BorderLayout.NORTH); progress_pane.add(progress, BorderLayout.CENTER); content_pane.setLayout(new BorderLayout()); content_pane.add(progress_pane, BorderLayout.NORTH); content_pane.add(control_pane, BorderLayout.CENTER); // Display dialog.setLocation((screen_size.width - MDS_SIZE.width) / 2, (screen_size.height - MDS_SIZE.height) / 2); on_screen = dialog; on_screen.setVisible(true); // Blocks until hidden. on_screen.dispose(); on_screen = null; content_pane = null; str_new = null; opt_new = null; ass_new = null; details_new = null; current_details_pane = null; new_details_pane = null; details_pane = null; button_pane = null; control_pane = null; progress_pane = null; dialog = null; if(mde_cur == null && action == Declarations.MERGE) { action = Declarations.FORCE_MERGE; } return action; } /** This method initialises the progress bar. * @param element_count An int specifying the total number of elements to be merged. */ public void startMerge(int element_count) { progress.setMaximum(element_count); progress.setMinimum(0); progress.setString("0%"); progress.setValue(0); } /** This method creates a prompt for renaming an Element. * @param mde_new The Element we wish to rename. * @return The new name as a String, null if cancelled. */ public String rename(Element mde_new) { action = Declarations.NO_ACTION; // Create JDialog dialog = new ModalDialog(Gatherer.g_man); dialog.setModal(true); dialog.setSize(RENAME_SIZE); dialog.setJMenuBar(new SimpleMenuBar("importingpreviouslyassignedmetadata")); Dictionary.setText(dialog, "MSMPrompt.Rename"); JLabel old_name_label = new JLabel(); old_name_label.setPreferredSize(RENAME_LABEL_SIZE); Dictionary.setText(old_name_label, "MSMPrompt.Old_Name"); JLabel old_name = new JLabel(mde_new.getAttribute("name")); old_name.setBackground(Color.white); old_name.setOpaque(true); JLabel new_name_label = new JLabel(); new_name_label.setPreferredSize(RENAME_LABEL_SIZE); Dictionary.setText(new_name_label, "MSMPrompt.New_Name"); JTextField new_name = new JTextField(""); new_name.grabFocus(); Dictionary.setTooltip(new_name, "MSMPrompt.New_Name_Tooltip"); JButton ok = new JButton(); ok.addActionListener(this); ok.setMnemonic(KeyEvent.VK_O); Dictionary.setBoth(ok, "General.OK", "General.OK_Tooltip"); JPanel content_pane = (JPanel) dialog.getContentPane(); // Layout JPanel old_name_pane = new JPanel(); old_name_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); old_name_pane.setLayout(new BorderLayout()); old_name_pane.add(old_name_label, BorderLayout.WEST); old_name_pane.add(old_name, BorderLayout.CENTER); JPanel new_name_pane = new JPanel(); new_name_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); new_name_pane.setLayout(new BorderLayout()); new_name_pane.add(new_name_label, BorderLayout.WEST); new_name_pane.add(new_name, BorderLayout.CENTER); JPanel control_pane = new JPanel(); control_pane.setLayout(new GridLayout(2,1)); control_pane.add(old_name_pane); control_pane.add(new_name_pane); JPanel button_pane = new JPanel(); button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); button_pane.setLayout(new GridLayout(1,2)); button_pane.add(ok); button_pane.add(cancel); content_pane.setLayout(new BorderLayout()); content_pane.add(control_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); // Display dialog.setLocation((screen_size.width - RENAME_SIZE.width) / 2, (screen_size.height - RENAME_SIZE.height) / 2); on_screen = dialog; on_screen.setVisible(true); on_screen.dispose(); on_screen = null; String result = new_name.getText(); button_pane = null; control_pane = null; new_name_pane = null; old_name_pane = null; content_pane = null; ok.removeActionListener(this); ok = null; new_name = null; new_name_label = null; old_name = null; old_name_label = null; dialog = null; if(action == Declarations.CANCEL) { return null; } action = Declarations.NO_ACTION; dialog = null; return result; } /** When called this method produces a nice error message on the screen, advising the user that the remove action has failed. * @param mde_cur The Element that we are attempting to remove. * @param reason The phrase key for the reason the rename failed, also as a String. */ public void removeFailed(Element mde_cur, String reason) { String args[] = new String[2]; args[0] = mde_cur.getAttribute("name"); args[1] = Dictionary.get(reason); JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("MSMPrompt.Remove_Failed", args), Dictionary.get("MSMPrompt.Remove_Failed_Title"), JOptionPane.ERROR_MESSAGE); } /** When called this method produces a nice error message on the screen, advising the user that the rename action has failed. * @param mde_new The Element that we are attempting to add. * @param new_name The name that we attempted to add it under, as a String. * @param reason The phrase key for the reason the rename failed, also as a String. */ public void renameFailed(Element mde_new, String new_name, String reason) { String args[] = new String[3]; args[0] = mde_new.getAttribute("name"); args[1] = new_name; args[2] = Dictionary.get(reason); JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("MSMPrompt.Rename_Failed", args), Dictionary.get("MSMPrompt.Rename_Failed_Title"), JOptionPane.ERROR_MESSAGE); } /** Method to display a prompt asking the user to select a specific element to merge with. * @param mds_cur The current MetadataSet. * @return The selected Element or null if the user cancels the action. */ public Element selectElement(MetadataSet mds_cur) { action = Declarations.NO_ACTION; // Create JDialog dialog = new ModalDialog(Gatherer.g_man); dialog.setModal(true); dialog.setSize(SELECT_SIZE); dialog.setJMenuBar(new SimpleMenuBar("importingpreviouslyassignedmetadata")); Dictionary.setText(dialog, "MSMPrompt.Select"); JButton ok = new JButton(); ok.addActionListener(this); ok.setMnemonic(KeyEvent.VK_O); ok.setEnabled(false); Dictionary.setBoth(ok, "General.OK", "General.OK_Tooltip"); Node elements_raw[] = ArrayTools.nodeListToNodeArray(mds_cur.getElements()); ElementWrapper elements[] = new ElementWrapper[elements_raw.length]; for(int i = 0; i < elements_raw.length; i++) { elements[i] = new ElementWrapper((Element)elements_raw[i]); } JList list = new JList(elements); ElementListListener element_list_listener = new ElementListListener(list, ok); list.addListSelectionListener(element_list_listener); JPanel content_pane = (JPanel) dialog.getContentPane(); // Layout JPanel list_pane = new JPanel(); list_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); list_pane.setLayout(new BorderLayout()); list_pane.add(new JScrollPane(list), BorderLayout.CENTER); JPanel button_pane = new JPanel(); button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); button_pane.setLayout(new GridLayout(1,2)); button_pane.add(ok); button_pane.add(cancel); content_pane.setLayout(new BorderLayout()); content_pane.add(list_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); // Display dialog.setLocation((screen_size.width - SELECT_SIZE.width) / 2, (screen_size.height - SELECT_SIZE.height) / 2); on_screen = dialog; on_screen.setVisible(true); on_screen.dispose(); on_screen = null; // get the result Element result = ((ElementWrapper)list.getSelectedValue()).getElement(); // Deallocate stuff since JDK1.4 won't. ok.removeActionListener(this); ok = null; elements_raw = null; elements = null; list.removeListSelectionListener(element_list_listener); list = null; element_list_listener = null; content_pane = null; list_pane = null; button_pane = null; dialog = null; // Return selected element if(action == Declarations.CANCEL) { return null; } return result; } /** Prompts the user to choose how to import a metadata element. Gives the option of renaming the element to a certain value of a certain set, or adding to a selected set. * @param name The name of the original metadata as a String. * @param set The set previously choosen as the default set for this metadata (which it doesn't match somehow). * @return An ElementWrapper around the element that it has been matched to. * @see org.greenstone.gatherer.msm.MSMPrompt.MSMDialog */ public ElementWrapper selectElement(String name) { dialog_cancelled = false; result = null; String args[] = new String[1]; args[0] = name; // Create MSMDialog dialog = new MSMDialog(); dialog.setModal(true); dialog.setSize(SELECT_ELEMENT_SIZE); dialog.setJMenuBar(new SimpleMenuBar("importingpreviouslyassignedmetadata")); Dictionary.setText(dialog, "MSMPrompt.Select_Element_Title"); JPanel content_pane = (JPanel) dialog.getContentPane(); JPanel control_pane = new JPanel(); JTextArea instructions = new JTextArea(); instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); instructions.setEditable(false); instructions.setLineWrap(true); instructions.setRows(SELECT_LINE_COUNT); instructions.setWrapStyleWord(true); Dictionary.setText(instructions, "MSMPrompt.Select_Element_Instructions", args); JPanel original_pane = new JPanel(); JLabel original_label = new JLabel(); original_label.setPreferredSize(SELECT_LABEL_SIZE); Dictionary.setText(original_label, "MSMPrompt.Select_Element_Original"); JTextField original = new JTextField(name); original.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); original.setEditable(false); JPanel set_pane = new JPanel(); JLabel set_label = new JLabel(); set_label.setPreferredSize(SELECT_LABEL_SIZE); Dictionary.setText(set_label, "MSMPrompt.Select_Element_Set"); JComboBox set = new JComboBox(manager.getSets(false)); // Don't include the greenstone metadata set. Dictionary.setTooltip(set, "MSMPrompt.Select_Element_Set_Tooltip"); JPanel element_pane = new JPanel(); JLabel element_label = new JLabel(); element_label.setPreferredSize(SELECT_LABEL_SIZE); Dictionary.setText(element_label, "MSMPrompt.Select_Element_Element"); JComboBox element = new JComboBox(); Dictionary.setTooltip(element, "MSMPrompt.Select_Element_Element_Tooltip"); JButton add_button = new JButton(); add_button.setEnabled(false); add_button.setMnemonic(KeyEvent.VK_A); Dictionary.setBoth(add_button, "MSMPrompt.Select_Element_Add", "MSMPrompt.Select_Element_Add_Tooltip"); JButton cancel_button = new JButton(); cancel_button.setMnemonic(KeyEvent.VK_C); Dictionary.setBoth(cancel_button, "General.Cancel", "General.Cancel_Tooltip"); JButton merge_button = new JButton(); merge_button.setEnabled(false); merge_button.setMnemonic(KeyEvent.VK_M); Dictionary.setBoth(merge_button, "MSMPrompt.Select_Element_Merge", "MSMPrompt.Select_Element_Merge_Tooltip"); JButton ignore_button = new JButton(); ignore_button.setMnemonic(KeyEvent.VK_I); Dictionary.setBoth(ignore_button, "MSMPrompt.Select_Element_Ignore", "MSMPrompt.Select_Element_Ignore_Tooltip"); JPanel button_pane = new JPanel(); // Connect AddListener add_listener = new AddListener(dialog, name, set); CancelListener cancel_listener = new CancelListener(dialog); IgnoreListener ignore_listener = new IgnoreListener(dialog); MergeListener merge_listener = new MergeListener(dialog, element); SetListener set_listener = new SetListener(set, element, name, add_button, merge_button); add_button.addActionListener(add_listener); cancel_button.addActionListener(cancel_listener); merge_button.addActionListener(merge_listener); ignore_button.addActionListener(ignore_listener); set.addActionListener(set_listener); // Init controls if(set.getItemCount() > 0) { // We now try to determine if there is any existing metadata // element whose name is the same as the new one. we ignore // any namespaces - if the name was a full match (namespace // and element name) then we wouldn't be in here MetadataSet closest_set = null; ElementWrapper closest_element = null; String base_name = name; int ns_sep = base_name.indexOf(MSMUtils.NS_SEP); if (ns_sep != -1) { base_name = base_name.substring(ns_sep+1); } for(int i = 0; i < set.getItemCount(); i++) { MetadataSet mds = (MetadataSet) set.getItemAt(i); for(int j = 0; j < mds.size(); j++) { Element mde = mds.getElement(j); String new_name = mde.getAttribute("name"); if (base_name.equals(new_name)) { closest_element = new ElementWrapper(mde); closest_set = mds; mde=null; break; } mde = null; } // for each element if (closest_element != null) { mds=null; break; } mds = null; } // for each set if(closest_set != null && closest_element != null) { set.setSelectedItem(closest_set); set_listener.actionPerformed(closest_element); } else { set_listener.actionPerformed((ElementWrapper)null); } closest_set = null; closest_element = null; } merge_button.setEnabled(element.getItemCount() > 0); // Layout original_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); original_pane.setLayout(new BorderLayout()); original_pane.add(original_label, BorderLayout.WEST); original_pane.add(original, BorderLayout.CENTER); set_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); set_pane.setLayout(new BorderLayout()); set_pane.add(set_label, BorderLayout.WEST); set_pane.add(set, BorderLayout.CENTER); element_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); element_pane.setLayout(new BorderLayout()); element_pane.add(element_label, BorderLayout.WEST); element_pane.add(element, BorderLayout.CENTER); control_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0)); control_pane.setLayout(new GridLayout(3,1)); control_pane.add(original_pane); control_pane.add(set_pane); control_pane.add(element_pane); button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0)); button_pane.setLayout(new GridLayout(1,4)); button_pane.add(add_button); button_pane.add(merge_button); button_pane.add(ignore_button); button_pane.add(cancel_button); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); content_pane.add(new JScrollPane(instructions), BorderLayout.NORTH); content_pane.add(control_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); // Display dialog.setLocation((screen_size.width - SELECT_ELEMENT_SIZE.width) / 2, (screen_size.height - SELECT_ELEMENT_SIZE.height) / 2); dialog.setVisible(true); // Deallocate everything because JDK1.4 won't. // Why, oh why did I do this? add_button.removeActionListener(add_listener); merge_button.removeActionListener(merge_listener); ignore_button.removeActionListener(ignore_listener); add_button = null; merge_button = null; ignore_button = null; add_listener = null; merge_listener = null; ignore_listener = null; // References args = null; content_pane = null; control_pane = null; instructions = null; original_pane = null; original_pane = null; original = null; element_pane = null; element_label = null; element = null; set_pane = null; set_label = null; set.removeActionListener(set_listener); set_listener = null; set = null; button_pane = null; dialog.dispose(); dialog.destroy(); dialog = null; // Dondage. return (ElementWrapper)result; } public boolean wasDialogCancelled() { return dialog_cancelled; } /** Prompts the user to select a metadata set from the given list. Uses the name parameter to attempt to automatically select the correct collection (ie the only collection that has an element with the same name). * @param name The name of the metadata element whose set name is unknown. * @return The metadata set the user has selected or null if no set selected. */ final public MetadataSet selectSet(String name) { String args[] = new String[1]; args[0] = name; // Creation MSMDialog dialog = new MSMDialog(); dialog.setModal(true); dialog.setSize(SELECT_SET_SIZE); dialog.setJMenuBar(new SimpleMenuBar("importingpreviouslyassignedmetadata")); Dictionary.setText(dialog, "MSMPrompt.Select_Set_Title"); JPanel content_pane = (JPanel) dialog.getContentPane(); JPanel control_pane = new JPanel(); JTextArea instructions = new JTextArea(); instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); instructions.setEditable(false); instructions.setLineWrap(true); instructions.setRows(SELECT_LINE_COUNT); instructions.setWrapStyleWord(true); Dictionary.setText(instructions, "MSMPrompt.Select_Set_Instructions", args); JComboBox set = new JComboBox(); set.setBackground(Color.white); set.addItem(Dictionary.get("MSMPrompt.Select_Set_None")); Vector sets = manager.getSets(); for(int i = sets.size() - 1; i >= 0; i--) { set.addItem(sets.get(i)); } Dictionary.setTooltip(set, "MSMPrompt.Select_Element_Set_Tooltip"); JButton ok = new JButton(); ActionListener ok_listener = new IgnoreListener(dialog); ok.addActionListener(ok_listener); // Doesn't really ignore. Just disposes() Dictionary.setBoth(ok, "General.OK", "General.OK_Tooltip"); // Select most likely set if(name.indexOf(".") != -1) { String set_name = name.substring(0, name.indexOf(".")); MetadataSet metadata_set = manager.getSet(set_name); if(metadata_set != null) { set.setSelectedItem(metadata_set); } metadata_set = null; set_name = null; } else { Vector matches = manager.setsThatContain(name); if(matches.size() == 1) { set.setSelectedItem(matches.get(0)); } matches = null; } // Layout control_pane.setLayout(new GridLayout(2,1)); control_pane.add(set); control_pane.add(ok); content_pane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); content_pane.setLayout(new BorderLayout()); content_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); content_pane.add(control_pane, BorderLayout.SOUTH); // Display dialog.setLocation((screen_size.width - SELECT_SET_SIZE.width) / 2, (screen_size.height - SELECT_SET_SIZE.height) / 2); dialog.setVisible(true); Object value = set.getSelectedItem(); if(value instanceof MetadataSet) { return (MetadataSet) value; } value = null; ok.removeActionListener(ok_listener); ok_listener = null; ok = null; content_pane = null; control_pane = null; instructions = null; set = null; dialog.destroy(); dialog = null; return null; } private class AddListener implements ActionListener { private JComboBox set = null; private JDialog dialog = null; private String name = null; public AddListener(JDialog dialog, String name, JComboBox set) { this.dialog = dialog; this.name = name; this.set = set; } public void actionPerformed(ActionEvent event) { // Get the currently selected metadata set. MetadataSet mds = (MetadataSet) set.getSelectedItem(); String n = name; // If we've been forced to go this far then any given namespace is complete bollocks. while(n.indexOf(".") != -1 && !n.equals(".")) { n = n.substring(n.indexOf(".") + 1); } // However, before we attempt to add a new element to the set, we should check that none already exists. Element element = mds.getElement(name); if (element == null) { result = mds.addElement(n, Gatherer.config.interface_language); } else { result = (ElementWrapper) element; } mds = null; n = null; element = null; dialog.setVisible(false); } } /** a ListCellRenderer for a list of Elements - the displayed value of the element is not Element.toString() */ private class AttributeListCellRenderer extends DefaultListCellRenderer { public AttributeListCellRenderer() { super(); } public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { setText(MSMUtils.getValue((Element)value)); if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } setEnabled(list.isEnabled()); setFont(list.getFont()); setOpaque(true); return this; } } /** This listener listens for selections within the select element to merge prompt, and once one has been made enables the ok button.*/ private class ElementListListener implements ListSelectionListener { /** The button we either enable or disable depending on user selection. */ private JButton ok = null; /** The list from whom we are listening for selection events. */ private JList list = null; /** Constructor. * @param list The JList from whom we are listening for selection events. * @param ok The JButton we either enable or disable depending on user selection. */ public ElementListListener(JList list, JButton ok) { this.list = list; this.ok = ok; } /** Any implementation of ListSelectionListener must include this method so we can be informed when a list selection event has occured. * @param event A ListSelectionEvent generated by the event. */ public void valueChanged(ListSelectionEvent event) { if(list.getSelectedValue() != null) { ok.setEnabled(true); } else { ok.setEnabled(false); } } } private class CancelListener implements ActionListener { private JDialog dialog = null; public CancelListener(JDialog dialog) { this.dialog = dialog; } public void actionPerformed(ActionEvent event) { dialog_cancelled = true; dialog.setVisible(false); } } private class IgnoreListener implements ActionListener { private JDialog dialog = null; public IgnoreListener(JDialog dialog) { this.dialog = dialog; } public void actionPerformed(ActionEvent event) { dialog.setVisible(false); } } private class MergeListener implements ActionListener { private JComboBox element = null; private JDialog dialog = null; public MergeListener(JDialog dialog, JComboBox element) { this.dialog = dialog; this.element = element; } public void actionPerformed(ActionEvent event) { // Return the currently selected element result = (ElementWrapper)element.getSelectedItem(); dialog.setVisible(false); } } private class MSMDialog extends ModalDialog { public MSMDialog() { super(Gatherer.g_man); } public void destroy() { rootPane = null; } } /** Listens to changes in the metadata set combobox */ private class SetListener implements ActionListener { private JButton add_button = null; private JButton merge_button = null; private JComboBox element_combobox = null; private JComboBox set_combobox = null; private String element_name = null; public SetListener(JComboBox set_combobox, JComboBox element_combobox, String element_name, JButton add_button, JButton merge_button) { this.element_name = element_name; this.element_combobox = element_combobox; this.set_combobox = set_combobox; this.add_button = add_button; this.merge_button = merge_button; } /** because the dialog constructor is selecting an element before calling actionPerformed, and actionPerformed is where the list of elements is built, we need to tell this what element should be selected */ public void actionPerformed(ElementWrapper selected_elem) { MetadataSet mds = (MetadataSet) set_combobox.getSelectedItem(); if (mds == null) { // If there is no metadata set selected, there isn't much you can do add_button.setEnabled(false); merge_button.setEnabled(false); return; } // Fill the element combobox with the elements of the selected metadata set element_combobox.removeAllItems(); Vector elements_list = mds.getElementsSorted(); for (int i = 0; i < elements_list.size(); i++) { element_combobox.addItem(elements_list.get(i)); } // If there is a pre-selected element, select it in the combobox if (selected_elem != null) { // If the element is not in the set, the selection won't change element_combobox.setSelectedItem(selected_elem); } // Can only add if the element doesn't already exist in the metadata set add_button.setEnabled(!mds.containsElement(element_name)); // Can only merge if the metadata set is not empty merge_button.setEnabled(mds.size() > 0); } public void actionPerformed(ActionEvent item) { actionPerformed((ElementWrapper) null); } } }