/** *######################################################################### * * A component of the Gatherer application, part of the Greenstone digital * library suite from the New Zealand Digital Library Project at th * 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.gems; import java.awt.*; import java.awt.event.*; import java.io.File; import java.io.PrintStream; import java.io.FileInputStream; import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.*; import javax.swing.*; import java.lang.String; import javax.swing.event.*; import javax.swing.filechooser.*; import javax.swing.text.*; import javax.swing.tree.*; import org.greenstone.gatherer.Configuration; import org.greenstone.gatherer.DebugStream; import org.greenstone.gatherer.Dictionary; import org.greenstone.gatherer.GetOpt; import org.greenstone.gatherer.cdm.*; import org.greenstone.gatherer.gui.GComboBox; import org.greenstone.gatherer.gui.GLIButton; import org.greenstone.gatherer.gui.HelpFrame; import org.greenstone.gatherer.gui.ModalDialog; import org.greenstone.gatherer.gui.NonWhitespaceField; import org.greenstone.gatherer.gui.TransformCharacterTextField; import org.greenstone.gatherer.util.Codec; import org.greenstone.gatherer.util.Utility; import org.w3c.dom.*; /** Provides a GUI and relevant suite of tools for the editing of the metadata set associated with this collection. Again I have tried to capture a file manager type feel, with a tree showing the various set-element relations to the left of the dialog, and the right side showing details on the current tree selection. When a set is selected these details include a list of attributes, while when an element is selected this list is joined by another showing assigned values. In order for the editor to be stable and consistant with the rest of the tool, care must be taken for fire appropriate events whenever the sets are changed. There is also the addded complexity of determining what actions have to occur in order for a users edit of an assigned value to be completed, i.e. if the user chooses to remove a value then a call must be made to record_set.root.removeMetadata() to ensure all such values are actually removed, so it is not enough just to remove the value from the value model. * @author John Thompson, Greenstone Digital Library, University of Waikato * @version 2.3b */ public class GEMS extends JFrame { static final public int ADD_SET = 0; static final public int NORMAL = 1; static final public int REMOVE_SET = 2; /** The default size of the editor dialog. */ static final private Dimension ADD_ELEMENT_SIZE = new Dimension(400,125); static final private Dimension RENAME_ELEMENT_SIZE = new Dimension(400, 95); static final private Dimension ADD_SET_SIZE = new Dimension(400,150); static final private Dimension RENAME_SET_SIZE = new Dimension(400,120); static final private Dimension OPEN_SETS_SIZE = new Dimension(400,135); static final private Dimension ADD_OR_EDIT_ATTRIBUTE_SIZE = new Dimension(600,325); static final private Dimension COMPONENT_SIZE = new Dimension(300,30); static final private Dimension SIZE = new Dimension(800,480); static final private String BLANK = "blank"; static final private String ELEMENT = "element"; static final private String SET = "set"; static final public String METADATA_SET_TEMPLATE = "xml/template.mds"; static final public String METADATA_VALUE_TEMPLATE = "xml/template.mdv"; //all of our popup menu items static final public int T_COLLECTION = 0; static final public int T_ELEMENT = 1; static final public int T_SET = 4; //static final public String MAX_LOADED_SETS = 64; static public Configuration config = null; private MetadataSetManager msm = new MetadataSetManager(this); public AddElementActionListener add_element_action_listener = null; public AddSetActionListener add_set_action_listener = null; /** The class used to handle add or edit attribute actions has to be globally available so that we can dispose of its dialog properly. */ public AddOrEditAttributeActionListener add_or_edit_attribute_action_listener = null; private boolean ignore = false; /** A card layout is used to switch between the two differing detail views. */ private CardLayout card_layout = null; /** Um, the size of the screen I'd guess. */ private Dimension screen_size = null; private ElementWrapper current_element = null; /** A reference to ourselves so our inner classes can dispose of us. */ private GEMS self = null; private String gsdl_path = null; private int current_attribute = -1; private int current_attribute_type = -1; //private JLabel element_name = null; private JLabel set_name = null; private JScrollPane element_attributes_scroll = null; private JScrollPane set_attributes_scroll = null; private JPanel details_pane = null; private GEMSModel model = null; private GEMSNode current_node = null; private MetadataSet current_set = null; public RemoveSetActionListener remove_set_action_listener; private SmarterTable element_attributes = null; private SmarterTable set_attributes = null; public org.w3c.dom.Element rootelement; //PopupListener provides right-click functionality to any component that needs it //It is a centralized manager for all popups, then we use evt.Source() and determine where the //event was performed private PopupListener popupListener = new PopupListener(this); /** A tree that represents the current metadata sets associated with this collection. */ private SmarterTree mds_tree = null; private String dialog_options[] = null; private boolean atLeastOneSetChanged = false; static public void main(String[] args) { // Parse arguments GetOpt go = new GetOpt(args); if (go.debug) { DebugStream.enableDebugging(); Calendar now = Calendar.getInstance(); String debug_file_path = "debug" + now.get(Calendar.DATE) + "-" + now.get(Calendar.MONTH) + "-" + now.get(Calendar.YEAR) + ".txt"; // Debug file is created in the GLI directory DebugStream.println("Debug file path: " + debug_file_path); DebugStream.setDebugFile(debug_file_path); } // Load configuration file try { config = new Configuration(go.gsdl_path, null, null); } catch (Exception exception) { DebugStream.printStackTrace(exception); } GEMS GEMS; GEMS = new GEMS(go.gsdl_path); } /** Constructor. * @param set a MetadataSet that should be initially selected * @param action a systematic action that should be performed */ public GEMS(String gsdl_path) { this.dialog_options = new String[2]; this.screen_size = config.screen_size; this.self = this; this.gsdl_path = gsdl_path; // Initialise some common images Utility.initImages(this); // Load help HelpFrame help = new HelpFrame(); dialog_options[0] = Dictionary.get("General.OK"); dialog_options[1] = Dictionary.get("General.Cancel"); // Load all the core metadata sets (in the GLI "metadata" directory) model = new GEMSModel(); File metadata_directory = new File(Utility.METADATA_DIR); if (metadata_directory.exists()) { // Load just those .mds files in this directory, and return them File[] directory_files = metadata_directory.listFiles(); for (int i = 0; i < directory_files.length; i++) { File child_file = directory_files[i]; if (!child_file.isDirectory() && child_file.getName().endsWith(".mds")) { System.err.println("Found mds file: " + child_file); MetadataSet metadata_set = msm.loadMetadataSet(child_file); model.add(null, metadata_set, GEMSNode.SET); } } } // Creation setDefaultCloseOperation(DISPOSE_ON_CLOSE); setSize(SIZE); setJMenuBar(new GEMSMenuBar()); Dictionary.setText(this, "GEMS.Title"); JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(config.getColor("coloring.collection_heading_background", false)); JPanel upper_pane = new JPanel(); upper_pane.setOpaque(false); JPanel set_details_pane = new JPanel(); set_details_pane.setOpaque(false); JPanel set_name_pane = new JPanel(); set_name_pane.setOpaque(false); JLabel set_name_label = new JLabel(); set_name_label.setOpaque(false); JPanel element_details_pane = new JPanel(); element_details_pane.setOpaque(false); JPanel element_inner_pane = new JPanel(); element_inner_pane.setOpaque(false); JPanel blank_pane = new JPanel(); // Some blank panel blank_pane.setOpaque(false); details_pane = new JPanel(); details_pane.setOpaque(false); card_layout = new CardLayout(); set_name = new JLabel(); JPanel mds_tree_pane = new JPanel(); mds_tree_pane.setOpaque(false); mds_tree_pane.setPreferredSize(new Dimension(300,500)); mds_tree = new SmarterTree(model); mds_tree.setCellRenderer(new GEMSTreeCellRenderer()); mds_tree.setRootVisible(false); mds_tree.setBackground(config.getColor("coloring.collection_tree_background", false)); mds_tree.setForeground(config.getColor("coloring.collection_tree_foreground", false)); mds_tree.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); mds_tree.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); //add popupevent handler for tree items mds_tree.addMouseListener(popupListener); mds_tree.addKeyListener(new KeyPressedHandler()); mds_tree.addTreeSelectionListener(new MDSTreeSelectionListener()); JPanel set_attributes_pane = new JPanel(); set_attributes_pane.setOpaque(false); set_attributes_scroll = new JScrollPane(); set_attributes_scroll.getViewport().setBackground(config.getColor("coloring.collection_tree_background", false)); set_attributes_scroll.setOpaque(true); set_attributes = new SmarterTable(); set_attributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); set_attributes.setBackground(config.getColor("coloring.collection_tree_background", false)); set_attributes.setForeground(config.getColor("coloring.collection_tree_foreground", false)); set_attributes.setHeadingBackground(config.getColor("coloring.collection_heading_background", false)); set_attributes.setHeadingForeground(config.getColor("coloring.collection_heading_foreground", false)); set_attributes.setOpaque(false); set_attributes.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); set_attributes.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); set_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); set_attributes.addMouseListener(popupListener); set_attributes.addMouseListener(new AddOrEditAttributeActionListener()); set_attributes.addKeyListener(new RemoveAttributeActionListener()); //Listen for DELETE key set_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(set_attributes)); JPanel element_attributes_pane = new JPanel(); element_attributes_pane.setOpaque(false); element_attributes_scroll = new JScrollPane(); element_attributes_scroll.getViewport().setBackground(config.getColor("coloring.collection_tree_background", false)); element_attributes_scroll.setOpaque(true); element_attributes = new SmarterTable(); element_attributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); element_attributes.setBackground(config.getColor("coloring.collection_tree_background", false)); element_attributes.setForeground(config.getColor("coloring.collection_tree_foreground", false)); element_attributes.setHeadingBackground(config.getColor("coloring.collection_heading_background", false)); element_attributes.setHeadingForeground(config.getColor("coloring.collection_heading_foreground", false)); element_attributes.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); element_attributes.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); element_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); element_attributes.addMouseListener(popupListener); element_attributes.addMouseListener(new AddOrEditAttributeActionListener()); element_attributes.addKeyListener(new RemoveAttributeActionListener()); //For the DELETE key element_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(element_attributes)); add_element_action_listener = new AddElementActionListener(); add_set_action_listener = new AddSetActionListener(); add_or_edit_attribute_action_listener = new AddOrEditAttributeActionListener(); remove_set_action_listener = new RemoveSetActionListener(); // Layout mds_tree_pane.setLayout(new BorderLayout()); mds_tree_pane.add(new JScrollPane(mds_tree), BorderLayout.CENTER); //Set panes set_name_pane.setLayout(new BorderLayout()); set_name_pane.add(set_name_label, BorderLayout.WEST); set_name_pane.add(set_name, BorderLayout.CENTER); set_attributes_scroll.setViewportView(set_attributes); set_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("GEMS.Attributes")), BorderFactory.createEmptyBorder(2,2,2,2))); set_attributes_pane.setLayout(new BorderLayout()); set_attributes_pane.add(set_attributes_scroll, BorderLayout.CENTER); set_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("GEMS.Set_Details")), BorderFactory.createEmptyBorder(2,2,2,2))); set_details_pane.setLayout(new BorderLayout()); set_details_pane.add(set_name_pane, BorderLayout.NORTH); set_details_pane.add(set_attributes_pane, BorderLayout.CENTER); //Element panes element_attributes_scroll.setViewportView(element_attributes); element_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("GEMS.Attributes")), BorderFactory.createEmptyBorder(2,2,2,2))); element_attributes_pane.setLayout(new BorderLayout()); element_attributes_pane.add(element_attributes_scroll, BorderLayout.CENTER); element_inner_pane.setLayout(new BorderLayout()); element_inner_pane.add(element_attributes_pane); element_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("GEMS.Element_Details")), BorderFactory.createEmptyBorder(2,2,2,2))); element_details_pane.setLayout(new BorderLayout()); element_details_pane.add(element_inner_pane, BorderLayout.CENTER); //General panes details_pane.setBorder(BorderFactory.createEmptyBorder(0,5,0,0)); details_pane.setLayout(card_layout); details_pane.add(blank_pane, BLANK); details_pane.add(set_details_pane, SET); details_pane.add(element_details_pane, ELEMENT); upper_pane.setLayout(new BorderLayout()); upper_pane.add(mds_tree_pane, BorderLayout.WEST); upper_pane.add(details_pane, BorderLayout.CENTER); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); content_pane.add(upper_pane, BorderLayout.CENTER); // initialise the selection mds_tree.setSelectionRow(0); // Display setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2); setVisible(true); } private void exit() { if(atLeastOneSetChanged == true) { int result = JOptionPane.showConfirmDialog(self, Dictionary.get("GEMS.Menu.Confirm_Exit_Save", Dictionary.get("GEMS.Element")), Dictionary.get("GEMS.Menu.Confirm_Exit_Save_Title"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if(result == 0) { DebugStream.closeDebugStream(); msm.save(); System.exit(0); } else if(result == 1) { DebugStream.closeDebugStream(); System.exit(0); } else if(result == 2) { //do nothing } } else { //Just exit DebugStream.closeDebugStream(); System.exit(0); } } private class GEMSMenuBar extends JMenuBar implements ActionListener { private JMenu file = null; private JMenu edit = null; private JMenu help = null; public JMenuItem file_exit = null; public JMenuItem file_new = null; public JMenuItem file_open = null; public JMenuItem file_save = null; public JMenuItem edit_copy = null; public JMenuItem edit_cut = null; public JMenuItem edit_paste = null; public JMenuItem help_help = null; public JMenuItem file_delete = null; public JMenuItem file_preferences = null; public GEMSMenuBar() { file = new JMenu(); file.setMnemonic(KeyEvent.VK_F); Dictionary.registerText(file, "Menu.File"); file_exit = new JMenuItem(); file_exit.addActionListener(this); file_exit.setMnemonic(KeyEvent.VK_X); Dictionary.registerText(file_exit, "Menu.File_Exit"); file_new = new JMenuItem(); file_new.addActionListener(this); file_new.setMnemonic(KeyEvent.VK_N); Dictionary.registerText(file_new, "Menu.File_New"); file_open = new JMenuItem(); file_open.addActionListener(this); file_open.setMnemonic(KeyEvent.VK_O); Dictionary.registerText(file_open, "Menu.File_Open"); file_save = new JMenuItem(); file_save.addActionListener(this); file_save.setMnemonic(KeyEvent.VK_S); Dictionary.registerText(file_save, "Menu.File_Save"); file_delete = new JMenuItem(); file_delete.addActionListener(new KeyPressedHandler()); //KeyPressedHandler handles deleting stuff. file_delete.setMnemonic(KeyEvent.VK_S); Dictionary.registerText(file_delete, "Menu.File_Delete"); file_preferences = new JMenuItem(); file_preferences.addActionListener(this); file_preferences.setMnemonic(KeyEvent.VK_S); Dictionary.registerText(file_preferences, "Menu.File_Options"); // Layout (file menu) file.add(file_new); file.add(file_open); file.add(file_save); file.add(file_delete); file.add(new JSeparator()); file.add(file_preferences); file.add(new JSeparator()); file.add(file_exit); // Edit menu edit = new JMenu(); edit.setMnemonic(KeyEvent.VK_E); Dictionary.registerText(edit, "Menu.Edit"); edit_cut = new JMenuItem(); edit_cut.addActionListener(this); edit_cut.setMnemonic(KeyEvent.VK_X); Dictionary.registerText(edit_cut, "Menu.Edit_Cut"); edit_copy = new JMenuItem(); edit_copy.addActionListener(this); edit_copy.setMnemonic(KeyEvent.VK_C); Dictionary.registerText(edit_copy, "Menu.Edit_Copy"); edit_paste = new JMenuItem(); edit_paste.addActionListener(this); edit_paste.setMnemonic(KeyEvent.VK_V); Dictionary.registerText(edit_paste, "Menu.Edit_Paste"); // Layout (edit menu) edit.add(edit_cut); edit.add(edit_copy); edit.add(edit_paste); // Help menu. Is not used! --Matthew help = new JMenu(); help.setIcon(Utility.HELP_ICON); Dictionary.setText(help, "GEMS.Menu.Help"); help_help = new JMenuItem(); help_help.addActionListener(this); Dictionary.registerText(help_help, "GEMS.Menu.Help"); // Layout (help menu) help.add(help_help); // Layout (menu bar) this.add(file); this.add(Box.createHorizontalStrut(15)); this.add(edit); this.add(Box.createHorizontalGlue()); //this.add(help); } public void actionPerformed(ActionEvent event) { Object event_source = event.getSource(); // File -> New if (event_source == file_new) { AddSetActionListener rah = new AddSetActionListener(); rah.show(); return; } // File -> Open if (event_source == file_open) { //we first launch the dialog to determine where the jfilechooser should be opened //ie: for collection specific sets - attila dec10-04 String set_directory = Utility.METADATA_DIR; SetSelectionDialog m = new SetSelectionDialog(); m.show(); //once we have clicked 'ok' on the jdialog above, then we should have //the directory pointer in string set_directory...and pass it to the jfilechoose constru return; } // File -> Save if (event_source == file_save) { msm.save(); atLeastOneSetChanged = false; return; } // File -> Exit if (event_source == file_exit) { exit(); //The exit() method checks if data needs saving. } // File -> Preferences if(event_source == file_preferences){ GEMSPreferences GemsPreferences = new GEMSPreferences(); } // Edit -> Cut if (event_source == edit_cut) { try { KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); // Get the component with selected text as a JTextComponent JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner(); // Cut the text to the clipboard text.cut(); } catch (ClassCastException cce) { // If the component is not a text component ignore the cut command DebugStream.println(cce.toString()); } return; } // Edit -> Copy if (event_source == edit_copy) { try { KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); // Get the component with selected text as a JTextComponent JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();//getFocusOwner(); text.copy(); } catch (Exception cce) { // If the component is not a text component ignore the copy command DebugStream.println(cce.toString()); } return; } // Edit -> Paste if (event_source == edit_paste) { try { KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); // Get the component with selected text as a JTextComponent JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner(); // Cut the text to the clipboard text.paste(); } catch (ClassCastException cce) { // If the component is not a text component ignore the paste command DebugStream.println(cce.toString()); } return; } // Help -> Help if (event_source == help_help) { HelpFrame.setView("editingmetadatasets"); return; } } } private class MetadataSetFileFilter extends FileFilter { public boolean accept(File file) { String file_name = file.getName().toLowerCase(); return(file_name.endsWith(".mds") || file_name.indexOf(".") == -1); } public String getDescription() { return Dictionary.get("MetadataSet.Files"); } } private class ActionTask extends Thread { private int action; public ActionTask(int action) { this.action = action; } public void run() { boolean complete = false; while(!complete) { if(self.isVisible()) { switch(action) { case ADD_SET: add_set_action_listener.actionPerformed(new ActionEvent(this, 0, "Blarg!")); break; case REMOVE_SET: if(!mds_tree.isSelectionEmpty()) { remove_set_action_listener.actionPerformed(new ActionEvent(this, 0, "Blarg!")); } break; } complete = true; } else { try { synchronized(this) { wait(100); } } catch(Exception exception) { } } } } } //callback method protected void processWindowEvent(WindowEvent evt){ if(evt.getID() == WindowEvent.WINDOW_CLOSING){ exit(); } } //called from MetadataSetManager...I don't think it should be here anymore, but for now it's ok public void warn_cant_load_set(){ JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Already_Loaded_Set_Error"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } public void dispose() { //if anything has changed, warn user that they should save if(atLeastOneSetChanged == true) { int result = JOptionPane.showOptionDialog(self, Dictionary.get("GEMS.Menu.Confirm_Exit_Save", Dictionary.get("GEMS.Element")), Dictionary.get("GEMS.Menu.Confirm_Exit_Save_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]); // System.out.println("Exit: "+result); if(result == 0) { msm.save(); } } atLeastOneSetChanged = false; // Destructor card_layout = null; screen_size = null; self = null; details_pane = null; element_attributes = null; set_attributes = null; set_name = null; mds_tree = null; popupListener = null; // Dispose of inner dialogs if (add_element_action_listener != null) { add_element_action_listener.dispose(); add_element_action_listener = null; } if (add_or_edit_attribute_action_listener != null) { add_or_edit_attribute_action_listener.dispose(); add_or_edit_attribute_action_listener = null; } remove_set_action_listener = null; //close super.dispose(); } /** Class to handle adding or modifying element attributes. */ private class AddOrEditAttributeActionListener extends ModalDialog implements ActionListener, MouseListener { private boolean add_type = true; private ComboArea value = null; private JButton cancel_button = null; private JButton ok_button = null; private JComboBox language_box = null; private GComboBox name = null; private HashMap name_to_values = null; private JLabel target = null; private JLabel target_label = null; private Vector attributeLists = null; //org.w3c.dom.Document lang = Utility.parse("/home/arosmain/gsdl/gli/classes/xml/languages.xml", false); org.w3c.dom.Document lang = Utility.parse(Configuration.gsdl_path + "/gli/classes/xml/languages.xml", false); /** Constructor. */ public AddOrEditAttributeActionListener() { super(self); setModal(true); attributeLists = new Vector(); attributeLists.add("identifier"); attributeLists.add("comment"); attributeLists.add("definition"); attributeLists.add("name"); attributeLists.add("creator"); attributeLists.add("date"); attributeLists.add("contact"); attributeLists.add("family"); attributeLists.add("lastchanged"); attributeLists.add("language_dependant"); attributeLists.add("version"); attributeLists.add("datatype"); attributeLists.add("obligation"); attributeLists.add("maximum_occurence"); attributeLists.add("registration_authority"); setSize(ADD_OR_EDIT_ATTRIBUTE_SIZE); name_to_values = new HashMap(); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(config.getColor("coloring.collection_heading_background", false)); JPanel upper_pane = new JPanel(); upper_pane.setOpaque(false); JPanel labels_pane = new JPanel(); JPanel boxes_pane = new JPanel(); target_label = new JLabel(); target_label.setOpaque(false); target = new JLabel(); target.setOpaque(false); JLabel name_label = new JLabel(); name_label.setOpaque(false); Dictionary.setText(name_label, "GEMS.Name"); name = new GComboBox(); name.setEditable(true); Dictionary.setTooltip(name, "GEMS.Attribute_Name_Tooltip"); JLabel language_label = new JLabel(); language_label.setOpaque(false); Dictionary.setText(language_label, "GEMS.Language"); language_box = new JComboBox(); for(int n = 0; n < attributeLists.size(); n++){ name.add(attributeLists.get(n)); } Dictionary.setTooltip(language_box, "GEMS.Attribute_Language_Tooltip"); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); value = new ComboArea(Dictionary.get("GEMS.Values"), COMPONENT_SIZE); value.setOpaque(false); JTextArea v_text_area = (JTextArea) value.getTextComponent(); v_text_area.setBackground(config.getColor("coloring.collection_tree_background", false)); v_text_area.setForeground(config.getColor("coloring.collection_tree_foreground", false)); v_text_area.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); v_text_area.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(v_text_area, "GEMS.Attribute_Value_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); getRootPane().setDefaultButton(ok_button); Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip"); cancel_button = new GLIButton(); cancel_button.setMnemonic(KeyEvent.VK_C); Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip"); // Connection TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button); cancel_button.addActionListener(this); name.addActionListener(this); ok_button.addActionListener(this); ok_button_enabler.add((JTextComponent)name.getEditor()); // Assuming the default editor is a JTextField! // Layout labels_pane.setLayout(new GridLayout(3,1,0,5)); labels_pane.add(target_label); labels_pane.add(name_label); labels_pane.add(language_label); boxes_pane.setLayout(new GridLayout(3,1,0,5)); boxes_pane.add(target); boxes_pane.add(name); boxes_pane.add(language_box); upper_pane.setLayout(new BorderLayout(5,0)); upper_pane.add(labels_pane, BorderLayout.WEST); upper_pane.add(boxes_pane, BorderLayout.CENTER); value.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); button_pane.setLayout(new GridLayout(1,2,5,0)); button_pane.add(ok_button); button_pane.add(cancel_button); center_pane.setLayout(new BorderLayout()); center_pane.add(value, BorderLayout.CENTER); center_pane.add(button_pane, BorderLayout.SOUTH); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); content_pane.add(upper_pane, BorderLayout.NORTH); content_pane.add(center_pane, BorderLayout.CENTER); setLocation((config.screen_size.width - ADD_OR_EDIT_ATTRIBUTE_SIZE.width) / 2, (config.screen_size.height - ADD_OR_EDIT_ATTRIBUTE_SIZE.height) / 2); // create dom object for language_Box //GEMSLanguageManager GemsLangManager = new GEMSLanguageManager("/home/arosmain/gsdl/gli/classes/xml/languages.xml"); GEMSLanguageManager GemsLangManager = new GEMSLanguageManager(Configuration.gsdl_path + "/gli/classes/xml/languages.xml"); Vector languagecodes = GemsLangManager.getLanguageCodes(); for(int p = 0; p < languagecodes.size(); p++){ language_box.addItem(languagecodes.get(p).toString()); } String code = Configuration.getLanguage(); language_box.setSelectedItem(code); //System.out.println(code); } //Handle double clicks in the table. public void mouseClicked(MouseEvent e) { if(e.getSource() == element_attributes || e.getSource() == set_attributes) { if(e.getClickCount() == 2) //Double click { //Show the Edit Attribute dialog this.menuEditValue(); this.editAttribute(); } } } //These methods are required by interface MouseListener public void mouseEntered(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mousePressed(MouseEvent e){} public void mouseReleased(MouseEvent e){} /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to add a new attribute to the selected set or element. * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { Object source = event.getSource(); AttributeTableModel model = null; if(current_element != null) { target.setText(current_element.getName()); Dictionary.setText(target_label, "GEMS.Target"); } else if(current_set != null) { Dictionary.setText(target_label, "GEMS.Set"); target.setText(current_set.toString()); Dictionary.setText(target_label, "GEMS.Target"); } if (source == popupListener.menuEditValue) { this.menuEditValue(); } if(source == ok_button) { boolean success = true; // Add or edit a set/element attribute switch(current_attribute_type) { case GEMSNode.SET: model = (AttributeTableModel) set_attributes.getModel(); success = addOrEditSetAttribute(model); break; case GEMSNode.ELEMENT: model = (AttributeTableModel) element_attributes.getModel(); success = addOrEditElementAttribute(model); break; } if (success) { // Hide dialog atLeastOneSetChanged = true; setVisible(false); return; } else { //If no success (an attribute with that name already exists), do nothing. } } else if(source == cancel_button) { // Hide dialog setVisible(false); return; } else if(source == name) { //System.err.println("source is name"); Object object = name.getSelectedItem(); if(object != null) { java.util.List values = (java.util.List) name_to_values.get(object.toString()); if(value != null && values != null){ value.clear(); for(int i = 0; i < values.size(); i++) { value.add(values.get(i)); } } } } else if (source == popupListener.menuAddAttributeAttribute || source == popupListener.menuAddAttributeSet || source == popupListener.menuAddAttributeElement){ Dictionary.setText(this, "GEMS.AddAttribute"); for(int i = 0; i < attributeLists.size(); i++) { name.add(attributeLists.get(i).toString()); } name.setEnabled(true); setVisible(true); } else if(current_attribute != -1) { this.editAttribute(); } source = null; } private void menuEditValue() { AttributeTableModel tablemodel = null; String prevLang = new String(""); String prevValue = new String(""); add_type = false; //grab the table model based on what is currently selected switch(current_attribute_type) { case GEMSNode.SET: tablemodel = (AttributeTableModel) set_attributes.getModel(); //grab value in table prevLang = tablemodel.getValueAt(current_attribute,0).toString(); prevValue = tablemodel.getValueAt(current_attribute,1).toString(); break; case GEMSNode.ELEMENT: tablemodel = (AttributeTableModel) element_attributes.getModel(); //grab values in table( lang and value) prevLang = tablemodel.getValueAt(current_attribute,1).toString(); prevValue = tablemodel.getValueAt(current_attribute,2).toString(); break; default: //by default grab element_attr's tablemodel = (AttributeTableModel) element_attributes.getModel(); prevLang = tablemodel.getValueAt(current_attribute,1).toString(); prevValue = tablemodel.getValueAt(current_attribute,2).toString(); break; } language_box.setEnabled(false); //if a set attr is selected, then do not do any lang operations, other than setting index to -1 if(current_attribute_type != GEMSNode.SET) { //set the current language to show up in language_box(no lang if no lang specified) if(prevLang == null || prevLang.compareTo(" ")==0 || prevLang.compareTo("") == 0 || prevLang.compareTo(" ")==0) { language_box.setSelectedIndex(-1); } else { language_box.setSelectedItem(prevLang.toLowerCase()); } }// end currattr != GEMSnode.set else { language_box.setSelectedIndex(-1); }// end currattr == GEMSnode.set value.setText(prevValue); } private void editAttribute() { //System.err.println("just entered editAttribute"); //debug AttributeTableModel model = null; Dictionary.setText(this, "GEMS.EditAttribute"); switch(current_attribute_type) { case GEMSNode.ELEMENT: model = (AttributeTableModel) element_attributes.getModel(); break; case GEMSNode.SET: model = (AttributeTableModel) set_attributes.getModel(); break; } add_type = false; String name_str = (String) model.getValueAt(current_attribute, 0); String value_str = (String) model.getValueAt(current_attribute, model.getColumnCount() - 1); model = null; // Retrieve the appropriate value model java.util.List values = (java.util.List) name_to_values.get(name_str); // Only possible for collection file selections. if(values == null) { values = msm.getElements(); } name.setSelectedItem(name_str); name_str = null; for(int i = 0; i < values.size(); i++) { Object temp_value = values.get(i); if(temp_value instanceof ElementWrapper) { value.add(new NameElementWrapperEntry(temp_value)); } else { value.add(temp_value); } } values = null; value.setSelectedItem(value_str); value_str = null; setVisible(true); } private boolean addOrEditSetAttribute(AttributeTableModel model) { String new_name_str = name.getSelectedItem().toString(); String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM); String old_name_str = null; boolean cont = false; boolean edit = false; if(!add_type && current_attribute != -1) //If edit, grab the attribute's old name { old_name_str = (String) set_attributes.getValueAt(current_attribute, 0); edit = true; } // Check that there isn't already an entry for this attribute if (!model.contains(new_name_str, 0) || (edit && new_name_str.equals(old_name_str))) { if(edit) //If edit, remove old attribute { current_set.removeAttribute(old_name_str); model.removeRow(current_attribute); } // Add the new attribute current_set.addAttribute(new_name_str, value_str); // Update the attribute table model.add(new Attribute(new_name_str, value_str)); cont = true; } // Otherwise show an error message and do not proceed else { cont = false; JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Attribute_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } value_str = null; new_name_str = null; return cont; } private boolean addOrEditElementAttribute(AttributeTableModel model) { String new_name_str = name.getSelectedItem().toString(); String old_name_str = null; String language_code = (String) language_box.getSelectedItem(); String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM); String old_value_str = null; String old_lang_code = null; boolean cont = false; boolean edit = false; if(!add_type && current_attribute != -1) //An edit { Attribute old_attribute = model.getAttribute(current_attribute); old_value_str = old_attribute.value; old_lang_code = old_attribute.language; old_name_str = (String) element_attributes.getValueAt(current_attribute, 0); //get the old name. edit = true; } //Check that there isn't already an entry for this attribute if (!model.contains(new_name_str, 0) || (edit && new_name_str.equals(old_name_str))) { if(edit) //If this is an edit, remove the old attribute { current_element.removeAttribute(old_name_str, old_lang_code, old_value_str); model.removeRow(current_attribute); } // Add the new attribute //System.err.println("current_element is: " + current_element.toString()); //debug current_element.addAttribute(new_name_str, language_code, value_str); // Update the attribute table int row = model.add(new Attribute(new_name_str, language_code, value_str)); element_attributes.setRowSelectionInterval(row, row); cont = true; } // Otherwise show an error message and do not proceed else { cont = false; JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Attribute_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } value_str = null; language_code = null; new_name_str = null; return cont; } } private class AddSubelementActionListener extends AddElementActionListener implements ActionListener { public AddSubelementActionListener() { Dictionary.setText(this, "GEMS.Popup.menuAddSubelement"); Dictionary.setTooltip(name_field, "GEMS.Subelement_Name_Tooltip"); } public void actionPerformed(ActionEvent event) { Object source = event.getSource(); current_element = current_node.getElement(); //current_element here is used generically for a element or subelement. if(source == ok_button) //Add then dispose { String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM); current_set = msm.getSet(current_element.getNamespace()); if(current_set != null) { // If this subelement doesn't already exist. if(!current_element.containsSubelement(name_str)) { // Add it, String language_code = config.getLanguage(); ElementWrapper subelement = current_set.addElement(name_str, language_code, current_node); final GEMSNode new_node = model.add(current_node, subelement, GEMSNode.ELEMENT); //Then update the tree. //SwingUtilities.invokeLater is used so that expandPath works on new parents. SwingUtilities.invokeLater(new Runnable() { public void run() { mds_tree.expandPath(new TreePath(current_node.getPath())); //Expand element so can see subelement. mds_tree.getSelectionModel().setSelectionPath(new TreePath(new_node)); //works, but node on tree doesn't look hilighted!! } }); //Done. Finish up. subelement = null; setVisible(false); atLeastOneSetChanged = true; //mark as changed } else { //A subelement with the same name exists. Display an error message. JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Subelement_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } } else { //This should not happen. System.err.println("Error: current_set is null in AddSubelementActionListener"); } } else if(source == cancel_button) { setVisible(false); } else { set_field.setText(current_node.toString()); //set to the name of the subelement name_field.setText(""); setVisible(true); } } public void dispose() { cancel_button = null; ok_button = null; name_field = null; set_field = null; super.dispose(); } } private class AddElementActionListener extends ModalDialog implements ActionListener { protected JButton cancel_button = null; protected JButton ok_button = null; protected JLabel set_field = null; protected NonWhitespaceField name_field = null; public AddElementActionListener() { super(self); setModal(true); setSize(ADD_ELEMENT_SIZE); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(config.getColor("coloring.collection_heading_background", false)); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); Dictionary.setText(this, "GEMS.AddElement"); JPanel labels_pane = new JPanel(); labels_pane.setOpaque(false); JLabel set_label = new JLabel(); set_label.setOpaque(false); Dictionary.setText(set_label, "GEMS.Set"); set_field = new JLabel(); set_field.setOpaque(false); JPanel values_pane = new JPanel(); values_pane.setOpaque(false); JLabel name_label = new JLabel(); name_label.setOpaque(false); Dictionary.setText(name_label, "GEMS.Name"); name_field = new NonWhitespaceField(); name_field.setBackground(config.getColor("coloring.collection_tree_background", false)); name_field.setForeground(config.getColor("coloring.collection_tree_foreground", false)); name_field.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); name_field.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(name_field, "GEMS.Element_Name_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); getRootPane().setDefaultButton(ok_button); Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip"); cancel_button = new GLIButton(); cancel_button.setMnemonic(KeyEvent.VK_C); Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip"); TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button); // Connection cancel_button.addActionListener(this); ok_button.addActionListener(this); ok_button_enabler.add(name_field); // Layout labels_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); labels_pane.setLayout(new GridLayout(2,1)); labels_pane.add(set_label); labels_pane.add(name_label); values_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); values_pane.setLayout(new GridLayout(2,1)); values_pane.add(set_field); values_pane.add(name_field); center_pane.setLayout(new BorderLayout(5,5)); center_pane.add(labels_pane, BorderLayout.WEST); center_pane.add(values_pane, BorderLayout.CENTER); button_pane.setLayout(new GridLayout(1,2,0,5)); button_pane.add(ok_button); button_pane.add(cancel_button); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); content_pane.add(center_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); setLocation((config.screen_size.width - ADD_ELEMENT_SIZE.width) / 2, (config.screen_size.height - ADD_ELEMENT_SIZE.height) / 2); } /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if(source == ok_button) { // Add then dispose String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM); // If this element doesn't already exist. if(!current_set.containsElement(name_str)) { // Add it, String language_code = config.getLanguage(); ElementWrapper element = current_set.addElement(name_str, language_code, null); // Then update the tree model.add(current_node, element, GEMSNode.ELEMENT); //SwingUtilities.invokeLater is used so that expandPath works on new parents. SwingUtilities.invokeLater(new Runnable() { public void run() { mds_tree.expandPath(new TreePath(current_node.getPath())); //expand set. } }); // Done element = null; setVisible(false); //mark as changed atLeastOneSetChanged = true; current_set.setSetChanged(true); } // Otherwise show an error message and do not proceed. else { JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Element_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } name_str = null; } else if(source == cancel_button) { // Dispose setVisible(false); } else { if(current_set != null) { //Does this ever happen? --Matthew // You can't manually add elements to the Greenstone metadata set. if(!current_set.getNamespace().equals("")) { set_field.setText(current_set.toString()); name_field.setText(""); // Display setVisible(true); } // Warn the user that they can't do that dave. else { JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Cannot_Add_Elements_To_Greenstone_MDS"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } } } source = null; } public void dispose() { cancel_button = null; ok_button = null; name_field = null; set_field = null; super.dispose(); } } private class AddSetActionListener extends ModalDialog implements ActionListener { private JButton cancel_button = null; private JButton ok_button = null; private JTextField name_field = null; private JTextField namespace_field = null; private JComboBox existingSetJComboBox = new JComboBox(); public AddSetActionListener() { super(self); setModal(true); setSize(ADD_SET_SIZE); Dictionary.setText(this, "GEMS.AddSet"); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(config.getColor("coloring.collection_heading_background", false)); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); JPanel label_pane = new JPanel(); JPanel boxes_pane = new JPanel(); JLabel namespace_label = new JLabel(); namespace_label.setOpaque(false); Dictionary.setText(namespace_label, "GEMS.Namespace"); namespace_field = TransformCharacterTextField.createNamespaceTextField(); namespace_field.setBackground(config.getColor("coloring.collection_tree_background", false)); namespace_field.setForeground(config.getColor("coloring.collection_tree_foreground", false)); namespace_field.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); namespace_field.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(namespace_field, "GEMS.Set_Namespace_Tooltip"); JLabel name_label = new JLabel(); name_label.setOpaque(false); Dictionary.setText(name_label, "GEMS.Name"); name_field = new JTextField(); name_field.setBackground(config.getColor("coloring.collection_tree_background", false)); name_field.setForeground(config.getColor("coloring.collection_tree_foreground", false)); name_field.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); name_field.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(name_field, "GEMS.Set_Name_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); getRootPane().setDefaultButton(ok_button); Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip"); cancel_button = new GLIButton(); cancel_button.setMnemonic(KeyEvent.VK_C); Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip"); TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button); // Connection cancel_button.addActionListener(this); ok_button.addActionListener(this); ok_button_enabler.add(name_field); ok_button_enabler.add(namespace_field); // Layout label_pane.setLayout(new GridLayout(3,1)); label_pane.add(name_label); label_pane.add(namespace_label); boxes_pane.setLayout(new GridLayout(3,1)); boxes_pane.add(name_field); boxes_pane.add(namespace_field); JLabel inheritJLabel = new JLabel(); Dictionary.setText(inheritJLabel, "GEMS.inheritMetadataSet"); label_pane.add(inheritJLabel); int getSetsLen = msm.getSets().toArray().length; Vector theSets = msm.getSets(); for(int k = 0; k < theSets.size(); k++){ MetadataSet ms = (MetadataSet)theSets.elementAt(k); existingSetJComboBox.addItem(new String(ms.getName() + " #% " + ms.getFile().toString())); } //add sets to existingSetJComboBox JLabel dummyl = new JLabel(); Dictionary.setText(dummyl, "GEMS.Add_Set.No_Inherit"); existingSetJComboBox.addItem("Do not inherit"); existingSetJComboBox.setSelectedIndex(getSetsLen); boxes_pane.add(existingSetJComboBox); center_pane.setLayout(new BorderLayout(5,0)); center_pane.add(label_pane, BorderLayout.WEST); center_pane.add(boxes_pane, BorderLayout.CENTER); button_pane.setLayout(new GridLayout(1,2,0,5)); button_pane.add(ok_button); button_pane.add(cancel_button); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); content_pane.add(center_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); setLocation((config.screen_size.width - ADD_SET_SIZE.width) / 2, (config.screen_size.height - ADD_SET_SIZE.height) / 2); } private boolean a_set_exists_with_this_namespace(String namespace){ Vector p = msm.getSets(); boolean flag = false; for(int k = 0; k < p.size(); k++){ MetadataSet s = (MetadataSet)p.get(k); if(s.getNamespace().compareTo(namespace) == 0){ flag = true; } } return flag; } /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if(source == ok_button) { //this code below handles whether we inherit from an existing set or not String namespace_str = namespace_field.getText(); String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM); if (existingSetJComboBox.getSelectedItem().toString().trim().compareTo("Do not inherit") == 0){ // Ensure the set doesn't already exist if(a_set_exists_with_this_namespace(namespace_str) == false){ MetadataSet set = msm.addSet(namespace_str, name_str); //mark as set changed = true set.setSetChanged(true); atLeastOneSetChanged = true; // Update tree. model.add(null, set, GEMSNode.SET); // Done set = null; setVisible(false); } else{ JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Set_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } name_str = null; namespace_str = null; }//end do not inherit else { //Should change this to use XML parsing utilites --Matthew //lets grab the metadata we want to inherit from... String anitem = existingSetJComboBox.getSelectedItem().toString(); // if(msm.getSet(namespace_str) == null) { if(a_set_exists_with_this_namespace(namespace_field.getText()) == false){ //setup to read the filename from mds file String [] items = anitem.split("#%"); try { FileInputStream fstream = new FileInputStream(items[1].trim()); BufferedReader in = new BufferedReader(new InputStreamReader(fstream, "UTF8")); FileOutputStream out; PrintWriter p; //setup to write to filename from existing file try { out = new FileOutputStream(Utility.METADATA_DIR + "/"+ namespace_str + ".mds"); OutputStreamWriter pout = new OutputStreamWriter(out, "UTF8"); p = new PrintWriter(pout); while(in.ready()){ String nextline = in.readLine(); if(nextline.matches(".+namespace=\".+\".*") == true) { nextline = nextline.replaceFirst("namespace=\".+\"","namespace=\"" + namespace_str+ "\""); } else { nextline = nextline.replaceFirst(">.+",">" + name_str + ""); } p.print(nextline + "\n"); } p.close(); MetadataSet loadedset = msm.loadMetadataSet(new File(Utility.METADATA_DIR + "/" + namespace_str + ".mds")); model.add(null, loadedset, GEMSNode.SET); } catch(Exception e){ System.out.println("Print file error"); } } catch(Exception e){ System.out.println("File Input error"); } }//msm.getset(namespacE) == null else{ JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Set_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } setVisible(false); } } //if(source == ok_button) else if(source == cancel_button) { setVisible(false); } else { name_field.setText(""); setVisible(true); } } //actionPerformed public void dispose() { cancel_button = null; ok_button = null; name_field = null; super.dispose(); } } //// private class SetSelectionDialog extends ModalDialog implements ActionListener { private JButton cancel_button = null; private JButton ok_button = null; private JComboBox existingSetJComboBox = new JComboBox(); public SetSelectionDialog() { super(self); setModal(true); setSize(OPEN_SETS_SIZE); Dictionary.setText(this, "GEMS.Menu.File_Open"); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(config.getColor("coloring.collection_heading_background", false)); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); JPanel boxes_pane = new JPanel(); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); getRootPane().setDefaultButton(ok_button); Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip"); cancel_button = new GLIButton(); cancel_button.setMnemonic(KeyEvent.VK_C); Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip"); //TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button); // Connection cancel_button.addActionListener(this); ok_button.addActionListener(this); // Layout boxes_pane.setLayout(new GridLayout(4,1)); JLabel inheritJLabel = new JLabel(); Dictionary.setText(inheritJLabel, "GEMS.inheritMetadataSet"); File[] col_dir = new File(Configuration.gsdl_path + "/collect").listFiles(); existingSetJComboBox.addItem("Default Metadata Sets #% " + Configuration.gsdl_path + "gli/metadata"); for(int k = 0; k < col_dir.length; k++){ if(col_dir[k].isDirectory() && col_dir[k].getName().compareTo("CVS") != 0) { File metadir = new File(col_dir[k].toString() + "/metadata"); if(metadir.exists()) existingSetJComboBox.addItem(new String(col_dir[k].getName() + " Collection Sets #% " + col_dir[k].toString() + "/metadata")); } } //add sets to existingSetJComboBox existingSetJComboBox.setSelectedIndex(0); JLabel dummyl = new JLabel(); Dictionary.setText(dummyl, "GEMS.Add_Set.No_Inherit"); boxes_pane.add(new JLabel("Select which group of metadata sets you wish to edit:\n\n\n\n")); boxes_pane.add(new JLabel("\n")); boxes_pane.add(existingSetJComboBox); boxes_pane.add(new JLabel("\n")); button_pane.setLayout(new GridLayout(1,3,0,5)); button_pane.add(ok_button); button_pane.add(cancel_button); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); content_pane.add(boxes_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); setLocation((config.screen_size.width - ADD_SET_SIZE.width) / 2, (config.screen_size.height - ADD_SET_SIZE.height) / 2); } /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if(source == ok_button) { //this code below handles whether we inherit from an existing set or not // String namespace_str = namespace_field.getText(); //String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM); String loc = (String) existingSetJComboBox.getSelectedItem(); String [] whereto = loc.split("#%"); String set_directory = whereto[1].trim(); //load the jfilechooser: JFileChooser metadata_set_file_chooser = new JFileChooser(new File(set_directory)); metadata_set_file_chooser.setFileFilter(new MetadataSetFileFilter()); if (metadata_set_file_chooser.showDialog(this, Dictionary.get("General.Open")) == JFileChooser.APPROVE_OPTION) { MetadataSet metadata_set = msm.loadMetadataSet(metadata_set_file_chooser.getSelectedFile()); // Update tree //only update tree if the metadata_set return is not null(it will be null if set is already //opened-Attila - oct 19 0 4 if(metadata_set != null) { model.add(null, metadata_set, GEMSNode.SET); } } setVisible(false); } else if(source == cancel_button) { setVisible(false); } else { setVisible(true); } } public void dispose() { cancel_button = null; ok_button = null; super.dispose(); } } /* Class to handle removing set or element attributes. */ private class RemoveAttributeActionListener implements ActionListener, KeyListener { /** Any implementation of KeyListener must include these mothods. When the DELETE key is pressed, fire the actionPerformed event. @param e A KeyEvent containing information about the event. */ public void keyTyped(KeyEvent e){ //Do nothing } public void keyPressed(KeyEvent e) { if(e.getKeyCode() == java.awt.event.KeyEvent.VK_DELETE) { //DELETE key pressed actionPerformed((ActionEvent)null); //is there a better way? } } public void keyReleased(KeyEvent e) { //Do nothing } /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { if(current_attribute != -1) { int result = JOptionPane.showOptionDialog(self, Dictionary.get("GEMS.Confirm_Removal", Dictionary.get("GEMS.Attribute")), Dictionary.get("GEMS.Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]); // Remove this attribute if(result == 0) { ignore = true; //Attributes are tricky little beasties, as they can come from several different places and depend upon what other little beasties have been selected //Has an element been selected if(current_element != null) { // Remove element attribute String name = (String) element_attributes.getValueAt(current_attribute, 0); String language = (String) element_attributes.getValueAt(current_attribute, 1); String value = (String) element_attributes.getValueAt(current_attribute, 2); current_element.removeAttribute(name, language, value); // Refresh table ((AttributeTableModel)element_attributes.getModel()).removeRow(current_attribute); } else if(current_set != null) { String name = (String) set_attributes.getValueAt(current_attribute, 0); // Remove set attribute current_set.removeAttribute(name); // Refresh table ((AttributeTableModel)set_attributes.getModel()).removeRow(current_attribute); } ignore = false; atLeastOneSetChanged= true; } } else { System.err.println("Tried to remove attribute, but current_attribute == -1!!"); //This should not happen } } } /* Class to handle deletion of elements (including subelements). Last modified 2/02/05 by Matthew Whyte */ private class RemoveElementActionListener implements ActionListener { /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to provide an editing prompt. * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { if(current_element != null) { int result = JOptionPane.showOptionDialog(self, Dictionary.get("GEMS.Confirm_Removal", Dictionary.get("GEMS.Element")), Dictionary.get("GEMS.Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]); // Remove this attribute if(result == 0) { //Get the parent element GEMSNode parent_node = (GEMSNode)current_node.getParent(); ElementWrapper parent_wrapped = parent_node.getElement(); ignore = true; msm.removeElement(current_element, parent_wrapped); // Clear selection mds_tree.clearSelection(); model.remove(current_node); // Show a blank panel. card_layout.show(details_pane, BLANK); ignore = false; atLeastOneSetChanged = true; } } else { System.err.println("No element currently selected."); //This should not happen! } } } /** Class to handle renaming of a set and/or it's namespace. @author: Matthew Whyte Date last modified: 10/01/05 */ private class RenameSetActionListener extends ModalDialog implements ActionListener { private JButton cancel_button = null; private JButton ok_button = null; private JTextField name_field = null; private JTextField namespace_field = null; public RenameSetActionListener() { super(self); setModal(true); setSize(RENAME_SET_SIZE); Dictionary.setText(this, "GEMS.Rename_Set"); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(config.getColor("coloring.collection_heading_background", false)); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); JPanel label_pane = new JPanel(); JPanel boxes_pane = new JPanel(); JLabel namespace_label = new JLabel(); namespace_label.setOpaque(false); Dictionary.setText(namespace_label, "GEMS.Namespace"); namespace_field = TransformCharacterTextField.createNamespaceTextField(); namespace_field.setBackground(config.getColor("coloring.collection_tree_background", false)); namespace_field.setForeground(config.getColor("coloring.collection_tree_foreground", false)); namespace_field.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); namespace_field.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(namespace_field, "GEMS.Rename_Namespace_Tooltip"); JLabel name_label = new JLabel(); name_label.setOpaque(false); Dictionary.setText(name_label, "GEMS.Name"); name_field = new JTextField(); name_field.setBackground(config.getColor("coloring.collection_tree_background", false)); name_field.setForeground(config.getColor("coloring.collection_tree_foreground", false)); name_field.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); name_field.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(name_field, "GEMS.Rename_Name_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); getRootPane().setDefaultButton(ok_button); Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip"); cancel_button = new GLIButton(); cancel_button.setMnemonic(KeyEvent.VK_C); Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip"); TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button); // Connection cancel_button.addActionListener(this); ok_button.addActionListener(this); ok_button_enabler.add(name_field); ok_button_enabler.add(namespace_field); // Layout label_pane.setLayout(new GridLayout(2,1)); label_pane.add(name_label); label_pane.add(namespace_label); boxes_pane.setLayout(new GridLayout(2,1)); boxes_pane.add(name_field); boxes_pane.add(namespace_field); center_pane.setLayout(new BorderLayout(5,0)); center_pane.add(label_pane, BorderLayout.WEST); center_pane.add(boxes_pane, BorderLayout.CENTER); button_pane.setLayout(new GridLayout(1,2,0,5)); button_pane.add(ok_button); button_pane.add(cancel_button); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); content_pane.add(center_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); setLocation((config.screen_size.width - RENAME_SET_SIZE.width) / 2, (config.screen_size.height - RENAME_SET_SIZE.height) / 2); } private boolean a_set_exists_with_this_namespace(String namespace){ Vector p = msm.getSets(); boolean flag = false; for(int k = 0; k < p.size(); k++){ MetadataSet s = (MetadataSet)p.get(k); if(s.getNamespace().compareTo(namespace) == 0){ flag = true; } } return flag; } /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if(source == ok_button) { String namespace_str = namespace_field.getText(); String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM); //Note: The name in name_str is language dependent. However, currently GEMS does not create new sets with different names for different languages(?). String current_set_namespace = current_set.getNamespace(); //Ensure that the namespace is unique. if(!(a_set_exists_with_this_namespace(namespace_str)) || (namespace_str.equals(current_set_namespace))) { //Hide the set that are about to rename mds_tree.clearSelection(); model.remove(current_node); //Rename set & namespace msm.renameSet(current_set, namespace_str, name_str); //Add (renamed) set back to tree model.add(null, current_set, GEMSNode.SET); //Clean up card_layout.show(details_pane, BLANK); // Show a blank panel. ignore = false; atLeastOneSetChanged = true; setVisible(false); } // Otherwise show an error message and do not proceed. else { JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Set_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } name_str = null; } else if(source == cancel_button) { setVisible(false); //hide dialog } else { name_field.setText(current_set.getName()); //getName() doesn't work properly. Need to update MetadataSet.java //getName() only doesn't work when the name is exactly the same as the namespace. namespace_field.setText(current_set.getNamespace()); setVisible(true); //Show the dialog } source = null; } public void dispose() { cancel_button = null; ok_button = null; name_field = null; super.dispose(); } } /** Class to handle renaming of an element. @author: Matthew Whyte Date last modified: 10/01/05 */ private class RenameElementActionListener extends ModalDialog implements ActionListener { protected JButton cancel_button = null; protected JButton ok_button = null; //private JLabel label = null; protected NonWhitespaceField name_field = null; public RenameElementActionListener() { super(self); setModal(true); setSize(RENAME_ELEMENT_SIZE); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(config.getColor("coloring.collection_heading_background", false)); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); JPanel labels_pane = new JPanel(); labels_pane.setOpaque(false); JPanel values_pane = new JPanel(); values_pane.setOpaque(false); JLabel name_label = new JLabel(); name_label.setOpaque(false); Dictionary.setText(name_label, "GEMS.New_Name"); name_field = new NonWhitespaceField(); name_field.setBackground(config.getColor("coloring.collection_tree_background", false)); name_field.setForeground(config.getColor("coloring.collection_tree_foreground", false)); name_field.setSelectionColor(config.getColor("coloring.collection_selection_background", false)); name_field.setSelectedTextColor(config.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(name_field, "GEMS.Rename_Element_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); getRootPane().setDefaultButton(ok_button); Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip"); cancel_button = new GLIButton(); cancel_button.setMnemonic(KeyEvent.VK_C); Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip"); TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button); Dictionary.setText(this, "GEMS.Rename_Element"); // Connection cancel_button.addActionListener(this); ok_button.addActionListener(this); ok_button_enabler.add(name_field); // Layout labels_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); labels_pane.setLayout(new GridLayout(1,1)); //labels_pane.add(set_label); labels_pane.add(name_label); values_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); values_pane.setLayout(new GridLayout(1,1)); //values_pane.add(label); values_pane.add(name_field); center_pane.setLayout(new BorderLayout(5,5)); center_pane.add(labels_pane, BorderLayout.WEST); center_pane.add(values_pane, BorderLayout.CENTER); button_pane.setLayout(new GridLayout(1,2,0,5)); button_pane.add(ok_button); button_pane.add(cancel_button); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); content_pane.add(center_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); setLocation((config.screen_size.width - ADD_ELEMENT_SIZE.width) / 2, (config.screen_size.height - ADD_ELEMENT_SIZE.height) / 2); } /** 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 about the event. */ public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if(source == ok_button) { TreeNode selPath = current_node.getParent(); GEMSNode parent = (GEMSNode)selPath; MetadataSet currentSet = msm.getSet(current_element.getNamespace()); String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM); GEMSNode new_node = null; // If this element doesn't already exist. if(!currentSet.containsElement(name_str)) //Do the renaming! { model.remove(current_node); //Hide the element that are about to rename msm.renameElement(current_element, name_str); //rename the element //Add the new element new_node = model.add(parent, current_element, GEMSNode.ELEMENT); //mds_tree.setSelectionPath(new_node_path); //would like to do this but doesn't hilight tree :-( card_layout.show(details_pane, BLANK); // Show a blank panel. //finish up currentSet.setSetChanged(true); atLeastOneSetChanged = true; setVisible(false); } // Otherwise show an error message and do not proceed. else { JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Element_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } name_str = null; } else if(source == cancel_button) { setVisible(false); //hide dialog } else { name_field.setText(current_element.getNameOnly()); //show old name (without namespace) setVisible(true); //Show the dialog } source = null; } public void dispose() { cancel_button = null; ok_button = null; name_field = null; super.dispose(); } } /** Class to handle DELETE key presses on the tree. The class then fires the appropriate event to remove that element/set. Attributes in the table are handled directly by the RemoveAttributeActionListener Author: Matthew Whyte Date last modified: 25/01/05 */ private class KeyPressedHandler implements KeyListener, ActionListener { // All implementations of KeyListener requires these methods public void keyTyped(KeyEvent e){ //Do nothing } public void keyPressed(KeyEvent e) { if(e.getKeyCode() == java.awt.event.KeyEvent.VK_DELETE) //DELETE key pressed { this.removeItem(); } } public void keyReleased(KeyEvent e) { //Do nothing } public void actionPerformed(ActionEvent event) { this.removeItem(); } public void removeItem() { boolean cont = true; /** Check to see if more than one tree node/leaf is selected. If so don't continue. This could be updated to delete multiple nodes/leaves in the futere. But not me and not today!! */ TreePath[] multiSelectionCheck = mds_tree.getSelectionPaths(); if(multiSelectionCheck.length > 1) { cont = false; Toolkit.getDefaultToolkit().beep(); } if(cont) { //Check to see if pressed on Set or Element. TreePath selPath = mds_tree.getSelectionPath(); GEMSNode t = (GEMSNode)selPath.getLastPathComponent(); if(t.type == T_ELEMENT) //Remove the element { RemoveElementActionListener removeElement = new RemoveElementActionListener(); removeElement.actionPerformed((ActionEvent)null); } else if(t.type == T_SET) //Remove the whole set { RemoveSetActionListener removeSet = new RemoveSetActionListener(); removeSet.actionPerformed((ActionEvent)null); } } } } private class RemoveSetActionListener implements ActionListener { /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { if(current_set != null) { //If the current_set_filename is dls or dublin or ex and in the METADATA_DIR, then do //not let anyone remove them --Attila File current_set_filename = current_set.getFile(); if(current_set_filename.toString().compareTo(new String(Utility.METADATA_DIR+"dls.mds")) == 0 || current_set_filename.toString().compareTo(new String(Utility.METADATA_DIR+"dublin.mds")) == 0 || current_set_filename.toString().compareTo(new String(Utility.METADATA_DIR+"ex.mds")) == 0){ JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.Cannot_Delete_Core_Sets_Error"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); return; } int result = JOptionPane.showOptionDialog(self, Dictionary.get("GEMS.Confirm_Removal", Dictionary.get("GEMS.Set") + " " + Dictionary.get("GEMS.Cannot_Undo")), Dictionary.get("GEMS.Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]); // Remove the currently selected set if(result == 0) { ignore = true; msm.removeSet(current_set); // Clear selection mds_tree.clearSelection(); model.remove(current_node); card_layout.show(details_pane, BLANK); //Show a blank panel. ignore = false; } } } } /** Used to enable a certain target component if and only if all the registered text fields contain non-zero length strings. */ private class TextFieldEnabler implements DocumentListener { private boolean ignore = false; private Component target = null; private JTextComponent[] fields = null; public TextFieldEnabler(Component target) { super(); this.target = target; } public void add(JTextComponent field) { // Record this field as being one we depend upon if(fields == null) { fields = new JTextComponent[1]; fields[0] = field; } else { JTextComponent[] temp = new JTextComponent[fields.length + 1]; System.arraycopy(fields, 0, temp, 0, fields.length); temp[fields.length] = field; fields = temp; temp = null; } // Add the appropriate listener field.getDocument().addDocumentListener(this); } /** Gives notification that an attribute or set of attributes changed. */ public void changedUpdate(DocumentEvent e) { canEnable(); } /** Gives notification that there was an insert into the document. */ public void insertUpdate(DocumentEvent e) { canEnable(); } /** Gives notification that a portion of the document has been removed. */ public void removeUpdate(DocumentEvent e) { canEnable(); } private void canEnable() { if(!ignore) { ignore = true; boolean can_enable = true; for(int i = 0; can_enable && i < fields.length; i++) { can_enable = can_enable && (fields[i].getText().length() > 0); } target.setEnabled(can_enable); ignore = false; } } } private class AttributesListSelectionListener implements ListSelectionListener { private JTable table = null; public AttributesListSelectionListener(JTable table) { this.table = table; } public void valueChanged(ListSelectionEvent event) { if(!event.getValueIsAdjusting()) { current_attribute = table.getSelectedRow(); } } } private class MDSTreeSelectionListener implements TreeSelectionListener { public void valueChanged(TreeSelectionEvent event) { if(!ignore) { // Clear all variables based on previous tree selection current_element = null; current_set = null; // Now process the node selected TreePath path = event.getPath(); current_node = (GEMSNode)path.getLastPathComponent(); // What we show depends on the node type... AttributeTableModel atm = null; TreeSet attributes = null; current_attribute_type = current_node.getType(); switch(current_attribute_type) { case GEMSNode.ELEMENT: current_element = current_node.getElement(); atm = current_node.getModel(); if(atm == null) { atm = new AttributeTableModel(current_element.getAttributes(), Dictionary.get("GEMS.Name"), Dictionary.get("GEMS.Language_Code"), Dictionary.get("GEMS.Value"), ""); //current_node.setModel(atm); } element_attributes.setModel(atm); atm.setScrollPane(element_attributes_scroll); atm.setTable(element_attributes); card_layout.show(details_pane, ELEMENT); break; case GEMSNode.SET: current_set = current_node.getSet(); atm = current_node.getModel(); if(atm == null) { NamedNodeMap temp = current_set.getAttributes(); attributes = new TreeSet(); for(int i = 0; i < temp.getLength(); i++) { Attr attribute = (Attr) temp.item(i); // We don't show the namespace attribute, as it is used as a unique primary key and should never be changed or removed in itself. if(!attribute.getName().equals("namespace")) { attributes.add(new Attribute(attribute.getName(), attribute.getValue())); } attribute = null; } atm = new AttributeTableModel(attributes, Dictionary.get("GEMS.Name"), Dictionary.get("GEMS.Value"), ""); temp = null; } set_attributes.setModel(atm); atm.setScrollPane(set_attributes_scroll); atm.setTable(set_attributes); card_layout.show(details_pane, SET); attributes = null; break; default: // Show a blank panel. card_layout.show(details_pane, BLANK); } attributes = null; path = null; atm = null; } } } private class GEMSTreeCellRenderer extends DefaultTreeCellRenderer { public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); setToolTipText(value.toString()); return this; } } //PopupListener is our main manager for all right-click popups class PopupListener extends MouseAdapter implements ActionListener{ JPopupMenu setPopup; JPopupMenu elementPopup; JPopupMenu attributePopup; //all of our popup menu items EVER! JMenuItem menuAddAttributeSet; JMenuItem menuAddElement; JMenuItem menuRenameSet; JMenuItem menuRemoveSet; JMenuItem menuAddAttributeElement; JMenuItem menuAddSubelement; JMenuItem menuRenameElement; JMenuItem menuDeleteElement; JMenuItem menuAddAttributeAttribute; JMenuItem menuEditValue; JMenuItem menuDeleteAttribute; GEMS GEMSRef = null; PopupListener(GEMS g) { setPopup = new JPopupMenu(); elementPopup = new JPopupMenu(); attributePopup = new JPopupMenu(); //reference to our parent(GEMS), because some of the actionlisteners would not //work unless they were declared in GEMS, and I need a way to reference GEMS GEMSRef = g; //Create the menu items menuAddAttributeSet = new JMenuItem(); Dictionary.setText(menuAddAttributeSet, "GEMS.Popup.menuAddAttribute"); menuAddElement =new JMenuItem(); Dictionary.setText(menuAddElement,"GEMS.Popup.menuAddElement"); menuRenameSet = new JMenuItem(); Dictionary.setText(menuRenameSet,"GEMS.Popup.menuRenameSet"); menuRemoveSet = new JMenuItem(); Dictionary.setText(menuRemoveSet, "GEMS.Popup.menuRemoveSet"); menuAddAttributeElement=new JMenuItem(); Dictionary.setText(menuAddAttributeElement,"GEMS.Popup.menuAddAttribute"); menuAddSubelement=new JMenuItem(); Dictionary.setText(menuAddSubelement,"GEMS.Popup.menuAddSubelement"); menuRenameElement=new JMenuItem(); Dictionary.setText(menuRenameElement,"GEMS.Popup.menuRenameElement"); menuDeleteElement=new JMenuItem(); Dictionary.setText(menuDeleteElement,"GEMS.Popup.menuRemoveElement"); menuAddAttributeAttribute=new JMenuItem(); Dictionary.setText(menuAddAttributeAttribute,"GEMS.Popup.menuAddAttribute"); menuEditValue=new JMenuItem(); Dictionary.setText(menuEditValue,"GEMS.Popup.menuEditValue"); menuDeleteAttribute=new JMenuItem(); Dictionary.setText(menuDeleteAttribute,"GEMS.Popup.menuRemoveAttribute"); //Associate the menu items with the appropriate popups: setPopup.add(menuAddAttributeSet); setPopup.add(menuAddElement); setPopup.add(menuRenameSet); setPopup.add(menuRemoveSet); elementPopup.add(menuAddAttributeElement); elementPopup.add(menuAddSubelement); elementPopup.add(menuRenameElement); elementPopup.add(menuDeleteElement); attributePopup.add(menuAddAttributeAttribute); attributePopup.add(menuEditValue); attributePopup.add(menuDeleteAttribute); //Add appropriate action listeners to the menu items. menuAddAttributeSet.addActionListener(new AddOrEditAttributeActionListener()); menuAddElement.addActionListener(new AddElementActionListener()); menuRenameSet.addActionListener(new RenameSetActionListener()); menuRemoveSet.addActionListener(new RemoveSetActionListener()); menuAddAttributeElement.addActionListener(new AddOrEditAttributeActionListener()); menuAddSubelement.addActionListener(new AddSubelementActionListener()); menuRenameElement.addActionListener(new RenameElementActionListener()); menuDeleteElement.addActionListener(new RemoveElementActionListener()); menuEditValue.addActionListener(new AddOrEditAttributeActionListener()); menuDeleteAttribute.addActionListener(new RemoveAttributeActionListener()); menuAddAttributeAttribute.addActionListener(new AddOrEditAttributeActionListener()); } public void mouseClicked(MouseEvent e) { maybeShowPopup(e); } public void mousePressed(MouseEvent e){ maybeShowPopup(e); } public void mouseReleased(MouseEvent e) { maybeShowPopup(e); } private void maybeShowPopup(MouseEvent e) { TreePath selPath = mds_tree.getPathForLocation(e.getX(), e.getY()); Point p = null; if (e.isPopupTrigger()) { if(e.getSource() == mds_tree) { try { GEMSNode t = (GEMSNode)selPath.getLastPathComponent(); mds_tree.setSelectionPath(selPath); //Select node right-clicked on if(t.type == T_ELEMENT){ elementPopup.show(e.getComponent(), e.getX(), e.getY()); } else if(t.type == T_SET){ setPopup.show(e.getComponent(), e.getX(), e.getY()); } } catch(Exception NullPointerException) { //Right-clicked in tree area, but no item to select. Do nothing. } } else if(e.getSource() == set_attributes){ //When right-click on table of set attributes //Select the table row that was right-clicked on. p = e.getPoint(); set_attributes.changeSelection(set_attributes.rowAtPoint(p), set_attributes.columnAtPoint(p), false, false); attributePopup.show(e.getComponent(), e.getX(), e.getY()); } else if(e.getSource() == element_attributes) { //When right-click on table of element attributes //Select the table row that was right-clicked on. p = e.getPoint(); element_attributes.changeSelection(element_attributes.rowAtPoint(p), element_attributes.columnAtPoint(p), false, false); attributePopup.show(e.getComponent(), e.getX(), e.getY()); } } } public void actionPerformed(ActionEvent e) { //This should never happen!! System.err.println("Error: actionPerformed was called in class PopupListener. This should never happen!"); } } /** Wrap a ElementWrapper so we get its name when we ask for toString(), not its identifier. */ private class NameElementWrapperEntry implements Comparable { private ElementWrapper element_wrapper = null; public NameElementWrapperEntry(Object object) { this.element_wrapper = (ElementWrapper) object; } public int compareTo(Object object) { return element_wrapper.compareTo(object); } public boolean equals(Object object) { return element_wrapper.equals(object); } public String toString() { return element_wrapper.getName(); } } }