/** *######################################################################### * * 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.mem; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.tree.*; import org.greenstone.gatherer.Configuration; import org.greenstone.gatherer.Dictionary; import org.greenstone.gatherer.Gatherer; import org.greenstone.gatherer.cdm.LanguageListCellRenderer; import org.greenstone.gatherer.gui.ComboArea; import org.greenstone.gatherer.gui.GComboBox; import org.greenstone.gatherer.gui.GLIButton; import org.greenstone.gatherer.gui.SmarterTable; import org.greenstone.gatherer.gui.SmarterTree; import org.greenstone.gatherer.gui.SimpleMenuBar; import org.greenstone.gatherer.gui.ModalDialog; import org.greenstone.gatherer.gui.NonWhitespaceField; import org.greenstone.gatherer.gui.TransformCharacterTextField; import org.greenstone.gatherer.mem.Attribute; import org.greenstone.gatherer.mem.AttributeTableModel; import org.greenstone.gatherer.mem.MEMNode; import org.greenstone.gatherer.msm.ElementWrapper; import org.greenstone.gatherer.msm.MetadataSet; import org.greenstone.gatherer.util.Codec; import org.greenstone.gatherer.util.Utility; import org.greenstone.gatherer.valuetree.GValueModel; import org.greenstone.gatherer.valuetree.GValueNode; 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 MetadataEditorManager extends ModalDialog { 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 ADD_FILE_SIZE = new Dimension(400,125); static final private Dimension ADD_SET_SIZE = new Dimension(400,125); static final private Dimension ADD_OR_EDIT_ATTRIBUTE_SIZE = new Dimension(600,325); static final private Dimension ADD_OR_EDIT_VALUE_SIZE = new Dimension(600,440); 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 PROFILE = "profile"; static final private String SET = "set"; static final private String VALUES = "values"; private AddElementActionListener add_element_action_listener = null; private AddFileActionListener add_file_action_listener = null; private 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. */ private AddOrEditAttributeActionListener add_or_edit_attribute_action_listener = null; /** The class used to handle add or edit value actions has to be globally available so that we can dispose of its dialog properly. */ private AddOrEditValueActionListener add_or_edit_value_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; /** A card layout is used to switch between a value tree or an empty placeholder (if no value tree available). */ private CardLayout element_values_layout = null; /** Um, the size of the screen I'd guess. */ private Dimension screen_size = null; private ElementWrapper current_element = null; private GValueNode current_value_node = null; /** A reference to ourselves so our inner classes can dispose of us. */ private MetadataEditorManager self = null; private int current_attribute = -1; private int current_attribute_type = -1; private JButton add_attribute = null; private JButton add_element = null; private JButton add_file = null; private JButton add_set = null; private JButton add_value = null; private JButton close = null; private JButton edit_attribute = null; private JButton edit_value = null; private JButton remove_attribute = null; private JButton remove_element = null; private JButton remove_file = null; private JButton remove_set = null; private JButton remove_value = null; private JLabel element_name = null; private JLabel profile_name = null; private JLabel set_name = null; private JScrollPane element_attributes_scroll = null; private JScrollPane profile_attributes_scroll = null; private JScrollPane set_attributes_scroll = null; private JPanel details_pane = null; private JPanel element_values_pane = null; private KeepTreeRootExpandedListener keep_root_expanded_listener = null; private MEMModel model = null; private MEMNode current_node = null; private MetadataSet current_set = null; private Object target = null; private RemoveSetActionListener remove_set_action_listener; private SmarterTable element_attributes = null; private SmarterTable profile_attributes = null; private SmarterTable set_attributes = null; private SmarterTree element_values = null; /** A tree that represents the current metadata sets associated with this collection. */ private SmarterTree mds_tree = null; private String current_collection_file = null; private String dialog_options[] = null; /** Constructor. * @param set a MetadataSet that should be initially selected * @param action a systematic action that should be performed */ public MetadataEditorManager(MetadataSet set, int action) { super(Gatherer.g_man); this.dialog_options = new String[2]; this.screen_size = Configuration.screen_size; this.self = this; dialog_options[0] = Dictionary.get("General.OK"); dialog_options[1] = Dictionary.get("General.Cancel"); // Creation setDefaultCloseOperation(DISPOSE_ON_CLOSE); setModal(true); setSize(SIZE); setJMenuBar(new SimpleMenuBar("editingmetadatasets")); Dictionary.setText(this, "MEM.Title"); JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false)); JPanel upper_pane = new JPanel(); upper_pane.setOpaque(false); model = new MEMModel(); JPanel mds_tree_pane = new JPanel(); mds_tree_pane.setOpaque(false); mds_tree_pane.setPreferredSize(new Dimension(200,500)); mds_tree = new SmarterTree(model); mds_tree.setCellRenderer(new MEMTreeCellRenderer()); mds_tree.setRootVisible(false); mds_tree.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); mds_tree.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); mds_tree.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); mds_tree.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); // We may have been asked to select a cetain initial set if(set != null) { MEMNode root = (MEMNode) model.getRoot(); for(int i = 0; i < root.getChildCount(); i++) { MEMNode child = (MEMNode) root.getChildAt(i); if(set.equals(child.getUserObject())) { TreePath path = new TreePath(child.getPath()); mds_tree.setSelectionPath(path); mds_tree.expandPath(path); path = null; } child = null; } root = null; } details_pane = new JPanel(); details_pane.setOpaque(false); card_layout = new CardLayout(); 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); Dictionary.setText(set_name_label, "MEM.Name"); set_name = new JLabel(); set_name.setBorder(BorderFactory.createLoweredBevelBorder()); set_name.setOpaque(false); JPanel set_attributes_pane = new JPanel(); set_attributes_pane.setOpaque(false); set_attributes_scroll = new JScrollPane(); set_attributes_scroll.getViewport().setBackground(Configuration.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(Configuration.getColor("coloring.collection_tree_background", false)); set_attributes.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); set_attributes.setHeadingBackground(Configuration.getColor("coloring.collection_heading_background", false)); set_attributes.setHeadingForeground(Configuration.getColor("coloring.collection_heading_foreground", false)); set_attributes.setOpaque(false); set_attributes.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); set_attributes.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); set_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JPanel element_details_pane = new JPanel(); element_details_pane.setOpaque(false); JPanel element_name_pane = new JPanel(); element_name_pane.setOpaque(false); JLabel element_name_label = new JLabel(); element_name_label.setOpaque(false); Dictionary.setText(element_name_label, "MEM.Name"); element_name = new JLabel(); element_name.setBorder(BorderFactory.createLoweredBevelBorder()); element_name.setOpaque(false); JPanel element_inner_pane = new JPanel(); element_inner_pane.setOpaque(false); JPanel element_attributes_pane = new JPanel(); element_attributes_pane.setOpaque(false); element_attributes_scroll = new JScrollPane(); element_attributes_scroll.getViewport().setBackground(Configuration.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(Configuration.getColor("coloring.collection_tree_background", false)); element_attributes.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); element_attributes.setHeadingBackground(Configuration.getColor("coloring.collection_heading_background", false)); element_attributes.setHeadingForeground(Configuration.getColor("coloring.collection_heading_foreground", false)); element_attributes.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); element_attributes.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); element_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); element_values_layout = new CardLayout(); element_values_pane = new JPanel(); element_values_pane.setOpaque(false); element_values = new SmarterTree(); element_values.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); element_values.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); element_values.setRootVisible(false); element_values.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); element_values.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); JPanel element_novalues_pane = new JPanel(); keep_root_expanded_listener = new KeepTreeRootExpandedListener(); JPanel profile_details_pane = new JPanel(); profile_details_pane.setOpaque(false); JPanel profile_name_pane = new JPanel(); profile_name_pane.setOpaque(false); JLabel profile_name_label = new JLabel(); profile_name_label.setOpaque(false); Dictionary.setText(profile_name_label, "MEM.Name"); profile_name = new JLabel(); profile_name.setBorder(BorderFactory.createLoweredBevelBorder()); profile_name.setOpaque(false); JPanel profile_attributes_pane = new JPanel(); profile_attributes_pane.setOpaque(false); profile_attributes_scroll = new JScrollPane(); profile_attributes_scroll.getViewport().setBackground(Configuration.getColor("coloring.collection_tree_background", false)); profile_attributes_scroll.setOpaque(true); profile_attributes = new SmarterTable(); profile_attributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); profile_attributes.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); profile_attributes.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); profile_attributes.setHeadingBackground(Configuration.getColor("coloring.collection_heading_background", false)); profile_attributes.setHeadingForeground(Configuration.getColor("coloring.collection_heading_foreground", false)); profile_attributes.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); profile_attributes.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); profile_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); JPanel button_label_pane = new JPanel(); button_label_pane.setOpaque(false); JLabel attribute_label = new JLabel(); attribute_label.setOpaque(false); Dictionary.setText(attribute_label, "MEM.Attribute"); JLabel element_label = new JLabel(); element_label.setOpaque(false); Dictionary.setText(element_label, "MEM.Element"); JLabel file_label = new JLabel(); file_label.setOpaque(false); Dictionary.setText(file_label, "MEM.File"); JLabel set_label = new JLabel(); set_label.setOpaque(false); Dictionary.setText(set_label, "MEM.Set"); JLabel value_label = new JLabel(); value_label.setOpaque(false); Dictionary.setText(value_label, "MEM.Value"); JPanel inner_button_pane = new JPanel(); inner_button_pane.setOpaque(false); add_attribute = new GLIButton(); add_attribute.setMnemonic(KeyEvent.VK_4); Dictionary.setBoth(add_attribute, "MEM.Add", "MEM.Add_Attribute_Tooltip"); add_element = new GLIButton(); add_element.setMnemonic(KeyEvent.VK_3); Dictionary.setBoth(add_element, "MEM.Add", "MEM.Add_Element_Tooltip"); add_file = new GLIButton(); add_file.setMnemonic(KeyEvent.VK_2); Dictionary.setBoth(add_file, "MEM.Add", "MEM.Add_File_Tooltip"); add_set = new GLIButton(); add_set.setMnemonic(KeyEvent.VK_1); Dictionary.setBoth(add_set, "MEM.Add", "MEM.Add_Set_Tooltip"); add_value = new GLIButton(); add_value.setMnemonic(KeyEvent.VK_5); Dictionary.setBoth(add_value, "MEM.Add", "MEM.Add_Value_Tooltip"); edit_attribute = new GLIButton(); edit_attribute.setMnemonic(KeyEvent.VK_6); Dictionary.setBoth(edit_attribute, "MEM.Edit", "MEM.Edit_Attribute_Tooltip"); edit_value = new GLIButton(); edit_value.setMnemonic(KeyEvent.VK_7); Dictionary.setBoth(edit_value, "MEM.Edit", "MEM.Edit_Value_Tooltip"); remove_attribute = new GLIButton(); remove_attribute.setMnemonic(KeyEvent.VK_MINUS); Dictionary.setBoth(remove_attribute, "MEM.Remove", "MEM.Remove_Attribute_Tooltip"); remove_element = new GLIButton(); remove_element.setMnemonic(KeyEvent.VK_0); Dictionary.setBoth(remove_element, "MEM.Remove", "MEM.Remove_Element_Tooltip"); remove_file = new GLIButton(); remove_file.setMnemonic(KeyEvent.VK_9); Dictionary.setBoth(remove_file, "MEM.Remove", "MEM.Remove_File_Tooltip"); remove_set = new GLIButton(); remove_set.setMnemonic(KeyEvent.VK_8); Dictionary.setBoth(remove_set, "MEM.Remove", "MEM.Remove_Set_Tooltip"); remove_value = new GLIButton(); remove_value.setMnemonic(KeyEvent.VK_EQUALS); Dictionary.setBoth(remove_value, "MEM.Remove", "MEM.Remove_Value_Tooltip"); setControls(false, false, false, false, false, false, false, false, false, false, false, false); close = new GLIButton(); close.setMnemonic(KeyEvent.VK_C); Dictionary.setBoth(close, "General.Close", "General.Close_Tooltip"); add_element_action_listener = new AddElementActionListener(); add_file_action_listener = new AddFileActionListener(); add_set_action_listener = new AddSetActionListener(); add_or_edit_attribute_action_listener = new AddOrEditAttributeActionListener(); add_or_edit_value_action_listener = new AddOrEditValueActionListener(); remove_set_action_listener = new RemoveSetActionListener(); // Some blank panel JPanel blank_pane = new JPanel(); blank_pane.setOpaque(false); JPanel edit_file_pane = new JPanel(); edit_file_pane.setOpaque(false); JPanel edit_element_pane = new JPanel(); edit_element_pane.setOpaque(false); JPanel edit_set_pane = new JPanel(); edit_set_pane.setOpaque(false); // Connection add_attribute.addActionListener(add_or_edit_attribute_action_listener); add_element.addActionListener(add_element_action_listener); add_file.addActionListener(add_file_action_listener); add_set.addActionListener(add_set_action_listener); add_value.addActionListener(add_or_edit_value_action_listener); close.addActionListener(new CloseActionListener()); edit_attribute.addActionListener(add_or_edit_attribute_action_listener); edit_value.addActionListener(add_or_edit_value_action_listener); remove_attribute.addActionListener(new RemoveAttributeActionListener()); remove_element.addActionListener(new RemoveElementActionListener()); remove_file.addActionListener(new RemoveFileActionListener()); remove_set.addActionListener(remove_set_action_listener); remove_value.addActionListener(new RemoveValueActionListener()); element_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(element_attributes)); profile_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(profile_attributes)); set_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(set_attributes)); element_values.addTreeSelectionListener(new ElementValuesTreeSelectionListener()); mds_tree.addTreeSelectionListener(new MDSTreeSelectionListener()); // Layout mds_tree_pane.setLayout(new BorderLayout()); mds_tree_pane.add(new JScrollPane(mds_tree), BorderLayout.CENTER); 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("MEM.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("MEM.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_name_pane.setLayout(new BorderLayout()); element_name_pane.add(element_name_label, BorderLayout.WEST); element_name_pane.add(element_name, BorderLayout.CENTER); element_attributes_scroll.setViewportView(element_attributes); element_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Attributes")), BorderFactory.createEmptyBorder(2,2,2,2))); element_attributes_pane.setLayout(new BorderLayout()); element_attributes_pane.add(element_attributes_scroll, BorderLayout.CENTER); element_values_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Values")), BorderFactory.createEmptyBorder(2,2,2,2))); //element_values_pane.setLayout(new BorderLayout()); //element_values_pane.add(new JScrollPane(element_values), BorderLayout.CENTER); element_values_pane.setLayout(element_values_layout); element_values_pane.add(element_novalues_pane, BLANK); element_values_pane.add(new JScrollPane(element_values), VALUES); element_inner_pane.setLayout(new GridLayout(2,1)); element_inner_pane.add(element_attributes_pane); element_inner_pane.add(element_values_pane); element_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Element_Details")), BorderFactory.createEmptyBorder(2,2,2,2))); element_details_pane.setLayout(new BorderLayout()); //element_details_pane.add(element_name_pane, BorderLayout.NORTH); element_details_pane.add(element_inner_pane, BorderLayout.CENTER); profile_name_pane.setLayout(new BorderLayout()); profile_name_pane.add(profile_name_label, BorderLayout.WEST); profile_name_pane.add(profile_name, BorderLayout.CENTER); profile_attributes_scroll.setViewportView(profile_attributes); profile_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Profiles")), BorderFactory.createEmptyBorder(2,2,2,2))); profile_attributes_pane.setLayout(new BorderLayout()); profile_attributes_pane.add(profile_attributes_scroll, BorderLayout.CENTER); profile_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Profile_Details")), BorderFactory.createEmptyBorder(2,2,2,2))); profile_details_pane.setLayout(new BorderLayout()); //profile_details_pane.add(profile_name_pane, BorderLayout.NORTH); profile_details_pane.add(profile_attributes_pane, BorderLayout.CENTER); 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); details_pane.add(profile_details_pane, PROFILE); upper_pane.setLayout(new BorderLayout()); upper_pane.add(mds_tree_pane, BorderLayout.WEST); upper_pane.add(details_pane, BorderLayout.CENTER); button_label_pane.setLayout(new GridLayout(5,1,0,2)); button_label_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,2)); button_label_pane.add(set_label); button_label_pane.add(file_label); button_label_pane.add(element_label); button_label_pane.add(attribute_label); button_label_pane.add(value_label); inner_button_pane.setLayout(new GridLayout(5,3,0,2)); inner_button_pane.add(add_set); inner_button_pane.add(edit_set_pane); inner_button_pane.add(remove_set); inner_button_pane.add(add_file); inner_button_pane.add(edit_file_pane); inner_button_pane.add(remove_file); inner_button_pane.add(add_element); inner_button_pane.add(edit_element_pane); inner_button_pane.add(remove_element); inner_button_pane.add(add_attribute); inner_button_pane.add(edit_attribute); inner_button_pane.add(remove_attribute); inner_button_pane.add(add_value); inner_button_pane.add(edit_value); inner_button_pane.add(remove_value); button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0)); button_pane.setLayout(new BorderLayout()); button_pane.add(button_label_pane, BorderLayout.WEST); button_pane.add(inner_button_pane, BorderLayout.CENTER); button_pane.add(close, BorderLayout.EAST); content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); content_pane.setLayout(new BorderLayout()); content_pane.add(upper_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); // Callback - we may have been asked to perform some systematic action, but we can't do that until the dialog is visible, which in itself causes a problem as the dialog is modal and setVisible won't return until the dialog is cancelled. The solution is to spawn a task on a new thread which waits until the dialog is visible then calls doClick on the appropriate button. if(action != NORMAL) { ActionTask task = new ActionTask(action); task.start(); } // Display setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2); setVisible(true); } 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) { } } } } } public void dispose() { // Destructor card_layout = null; screen_size = null; self = null; add_attribute = null; add_element = null; add_file = null; add_set = null; add_value = null; close = null; edit_attribute = null; edit_value = null; remove_attribute = null; remove_element = null; remove_file = null; remove_set = null; remove_value = null; details_pane = null; element_attributes = null; set_attributes = null; element_name = null; set_name = null; element_values = null; mds_tree = null; target = 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; } if (add_or_edit_value_action_listener != null) { add_or_edit_value_action_listener.dispose(); add_or_edit_value_action_listener = null; } remove_set_action_listener = null; super.dispose(); } private void setControls(boolean a_s, boolean r_s, boolean a_f, boolean r_f, boolean a_e, boolean r_e, boolean a_a, boolean e_a, boolean r_a, boolean a_v, boolean e_v, boolean r_v) { add_attribute.setEnabled(a_a); add_element.setEnabled(a_e); add_file.setEnabled(true); // Always true add_set.setEnabled(true); // Always true add_value.setEnabled(a_v); edit_attribute.setEnabled(e_a); edit_value.setEnabled(e_v); remove_attribute.setEnabled(r_a); remove_element.setEnabled(r_e); remove_file.setEnabled(r_f); remove_set.setEnabled(r_s); remove_value.setEnabled(r_v); } private class AddOrEditAttributeActionListener extends ModalDialog implements ActionListener { 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; /** Constructor. */ public AddOrEditAttributeActionListener() { super(self); setModal(true); setSize(ADD_OR_EDIT_ATTRIBUTE_SIZE); name_to_values = new HashMap(); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(Configuration.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(); JLabel target_label = new JLabel(); target_label.setOpaque(false); Dictionary.setText(target_label, "MEM.Target"); target = new JLabel(); target.setOpaque(false); JLabel name_label = new JLabel(); name_label.setOpaque(false); Dictionary.setText(name_label, "MEM.Name"); name = new GComboBox(); name.setEditable(true); Dictionary.setTooltip(name, "MEM.Attribute_Name_Tooltip"); JLabel language_label = new JLabel(); language_label.setOpaque(false); Dictionary.setText(language_label, "MEM.Language"); language_box = new JComboBox(Gatherer.g_man.design_pane.getLanguageCodes().toArray()); language_box.setRenderer(new LanguageListCellRenderer()); Dictionary.setTooltip(language_box, "MEM.Attribute_Language_Tooltip"); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); value = new ComboArea(Dictionary.get("MEM.Values"), COMPONENT_SIZE); value.setOpaque(false); JTextArea v_text_area = (JTextArea) value.getTextComponent(); v_text_area.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); v_text_area.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); v_text_area.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); v_text_area.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(v_text_area, "MEM.Attribute_Value_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); 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((Configuration.screen_size.width - ADD_OR_EDIT_ATTRIBUTE_SIZE.width) / 2, (Configuration.screen_size.height - ADD_OR_EDIT_ATTRIBUTE_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 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(); if(source == ok_button) { boolean success = true; AttributeTableModel model; // Add or edit a collect/set/element attribute switch(current_attribute_type) { case MEMNode.COLLECTION: model = (AttributeTableModel) profile_attributes.getModel(); success = addOrEditCollectionAttribute(model); break; case MEMNode.SET: model = (AttributeTableModel) set_attributes.getModel(); success = addOrEditSetAttribute(model); break; case MEMNode.ELEMENT: model = (AttributeTableModel) element_attributes.getModel(); success = addOrEditElementAttribute(model); break; } if (success) { // Hide dialog setVisible(false); } } else if(source == cancel_button) { // Hide dialog setVisible(false); } else if(source == name) { Object object = name.getSelectedItem(); if(object != null) { java.util.List values = (java.util.List) name_to_values.get(object.toString()); if(values == null && current_attribute_type==MEMNode.COLLECTION) { values = Gatherer.c_man.msm.getElements(); } value.clear(); for(int i = 0; i < values.size(); i++) { value.add(values.get(i)); } } } else { // Name combo box is enabled except when attributes are edited //name.setEnabled((source != edit_attribute)); name_to_values.clear(); name.clear(); value.clear(); value.setText(""); // Build the correct name_to_values mapping // Attributes are slightly tricky as they can come from several sources. Has a collection file been selected... if(current_collection_file != null) { target.setText(current_collection_file); // Name is empty in this one, however values must be the current elements in the collection. language_box.setEnabled(false); } // or has an element been selected else if(current_element != null) { target.setText(current_element.toString()); // Develop a model for name based on known attributes from all other elements. java.util.List elements = Gatherer.c_man.msm.getElements(); for(int i = 0; i < elements.size(); i++) { ElementWrapper element = (ElementWrapper) elements.get(i); TreeSet attributes = element.getAttributes(); for(Iterator attribute_iterator = attributes.iterator(); attribute_iterator.hasNext(); ) { Attribute attribute = (Attribute) attribute_iterator.next(); java.util.List values = (java.util.List) name_to_values.get(attribute.name); if(values == null) { values = new ArrayList(); name_to_values.put(attribute.name, values); } if(!values.contains(attribute.value)) { values.add(attribute.value); } values = null; attribute = null; } attributes = null; element = null; } elements = null; language_box.setEnabled(true); } else if(current_set != null) { target.setText(current_set.toString()); // Develop a model for name based on known attributes from all other metadata sets. At the same time build a hashmap mapping attribute name to lists of values. java.util.List sets = Gatherer.c_man.msm.getSets(); for(int i = 0; i < sets.size(); i++) { MetadataSet set = (MetadataSet) sets.get(i); NamedNodeMap attributes = set.getAttributes(); for(int j = 0; j < attributes.getLength(); j++) { Attr attribute = (Attr) attributes.item(j); String name_str = attribute.getName(); String value_str = attribute.getValue(); java.util.List values = (java.util.List) name_to_values.get(name_str); if(values == null) { values = new ArrayList(); name_to_values.put(name_str, values); } if(!values.contains(value_str)) { values.add(value_str); } values = null; value_str = null; name_str = null; attribute = null; } attributes = null; set = null; language_box.setEnabled(false); } sets = null; // If this is an add remove all the attributes already present in the current set. if(source == add_attribute) { name.setEnabled(true); NamedNodeMap attributes = current_set.getAttributes(); for(int i = 0; i < attributes.getLength(); i++) { Attr attribute = (Attr) attributes.item(i); String name_str = attribute.getName(); name_to_values.remove(name_str); name_str = null; attribute = null; } attributes = null; } } // Otherwise we actually disable the name combobox else { name.setEnabled(false); } // Now name_to_values should contain a list of unique attribute names each mapping to a list of attribute values. for(Iterator name_iterator = name_to_values.keySet().iterator(); name_iterator.hasNext(); ) { name.add(name_iterator.next()); } // Now pritty up the dialog depending on the action type if(source == add_attribute) { add_type = true; Dictionary.setText(this, "MEM.AddAttribute"); if(current_collection_file != null) { // Name is empty in this one, however values must be the current elements in the collection. java.util.List values = Gatherer.c_man.msm.getElements(); for(int i = 0; i < values.size(); i++) { value.add(new NameElementWrapperEntry(values.get(i))); } values = null; } setVisible(true); } else if(current_attribute != -1) { AttributeTableModel model = null; switch(current_attribute_type) { case MEMNode.COLLECTION: model = (AttributeTableModel) profile_attributes.getModel(); break; case MEMNode.ELEMENT: model = (AttributeTableModel) element_attributes.getModel(); break; case MEMNode.SET: model = (AttributeTableModel) set_attributes.getModel(); break; } add_type = false; Dictionary.setText(this, "MEM.EditAttribute"); 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 = Gatherer.c_man.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); } } source = null; } private boolean addOrEditCollectionAttribute(AttributeTableModel model) { String name_str = name.getSelectedItem().toString(); String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM); // Remove the existing attribute if this is an edit if(!add_type && current_attribute != -1) { String old_source = (String) model.getValueAt(current_attribute, 0); Gatherer.c_man.msm.profiler.removeAction(current_collection_file, old_source); old_source = null; model.removeRow(current_attribute); } boolean cont = true; // Check that there isn't already an entry for this attribute if (!model.contains(name_str, 0)) { // Add profile Gatherer.c_man.msm.profiler.addAction(current_collection_file, name_str, value_str); // Update attribute table model.add(new Attribute(name_str, value_str)); } // Otherwise show an error message and do not proceed else { cont = false; JOptionPane.showMessageDialog(self, Dictionary.get("MEM.Attribute_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } value_str = null; name_str = null; return cont; } private boolean addOrEditSetAttribute(AttributeTableModel model) { String name_str = name.getSelectedItem().toString(); String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM); // Remove the existing attribute if this is an edit if(!add_type && current_attribute != -1) { current_set.removeAttribute(name_str); // Update attribute table model.removeRow(current_attribute); } boolean cont = true; // Check that there isn't already an entry for this attribute if (!model.contains(name_str, 0)) { // Add the new attribute current_set.addAttribute(name_str, value_str); // Update the attribute table model.add(new Attribute(name_str, value_str)); } // Otherwise show an error message and do not proceed else { cont = false; JOptionPane.showMessageDialog(self, Dictionary.get("MEM.Attribute_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } value_str = null; name_str = null; return cont; } private boolean addOrEditElementAttribute(AttributeTableModel model) { // Add the attribute, even if one of the same name already exists. Maybe one day someone would like to enforce the occurance rules but not me and not today. String name_str = name.getSelectedItem().toString(); String language_code = (String) language_box.getSelectedItem(); String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM); // Remove the existing attribute if this is an edit if(!add_type && current_attribute != -1) { Attribute old_attribute = model.getAttribute(current_attribute); String old_value_str = old_attribute.value; String old_lang_code = old_attribute.language; current_element.removeAttribute(name_str, old_lang_code, old_value_str); // Update the attribute table model.removeRow(current_attribute); } // Add the new attribute current_element.addAttribute(name_str, language_code, value_str); // Update the attribute table int row = model.add(new Attribute(name_str, language_code, value_str)); element_attributes.setRowSelectionInterval(row, row); value_str = null; language_code = null; name_str = null; return true; } public void dispose() { cancel_button = null; name = null; name_to_values = null; ok_button = null; target = null; value = null; ///ystem.err.println("Dispose AddOrEditAttributeActionListener"); super.dispose(); } } private class AddElementActionListener extends ModalDialog implements ActionListener { private JButton cancel_button = null; private JButton ok_button = null; private JLabel set_field = null; private NonWhitespaceField name_field = null; public AddElementActionListener() { super(self); setModal(true); setSize(ADD_ELEMENT_SIZE); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false)); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); JPanel set_pane = new JPanel(); set_pane.setOpaque(false); JLabel set_label = new JLabel(); set_label.setOpaque(false); Dictionary.setText(set_label, "MEM.Set"); set_field = new JLabel(); set_field.setOpaque(false); JPanel name_pane = new JPanel(); name_pane.setOpaque(false); JLabel name_label = new JLabel(); name_label.setOpaque(false); Dictionary.setText(name_label, "MEM.Name"); name_field = new NonWhitespaceField(); name_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); name_field.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); name_field.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); name_field.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(name_field, "MEM.Element_Name_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); 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 set_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); set_pane.setLayout(new BorderLayout()); set_pane.add(set_label, BorderLayout.WEST); set_pane.add(set_field, BorderLayout.CENTER); name_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); name_pane.setLayout(new BorderLayout(5,0)); name_pane.add(name_label, BorderLayout.WEST); name_pane.add(name_field, BorderLayout.CENTER); center_pane.setLayout(new GridLayout(2,1,0,0)); center_pane.add(set_pane); center_pane.add(name_pane); 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((Configuration.screen_size.width - ADD_ELEMENT_SIZE.width) / 2, (Configuration.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 = Configuration.getLanguage(); ElementWrapper element = current_set.addElement(name_str, language_code); // Then update the tree model.add(current_node, element, MEMNode.ELEMENT); // Signal that the metadata set has changed Gatherer.c_man.msm.fireSetChanged(current_set); // Done element = null; setVisible(false); } // Otherwise show an error message and do not proceed. else { JOptionPane.showMessageDialog(self, Dictionary.get("MEM.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) { // 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("MEM.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; ///ystem.err.println("Dispose AddElementActionListener"); super.dispose(); } } private class AddFileActionListener extends ModalDialog implements ActionListener { private JButton cancel_button = null; private JButton ok_button = null; private JTextField name_field = null; public AddFileActionListener() { super(self); setModal(true); setSize(ADD_FILE_SIZE); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false)); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); JPanel profile_pane = new JPanel(); profile_pane.setOpaque(false); JLabel profile_label = new JLabel(); profile_label.setOpaque(false); Dictionary.setText(profile_label, "MEM.Profile"); JPanel name_pane = new JPanel(); name_pane.setOpaque(false); JLabel name_label = new JLabel(); name_label.setOpaque(false); Dictionary.setText(name_label, "MEM.Name"); name_field = new JTextField(); name_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); name_field.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); name_field.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); name_field.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(name_field, "MEM.Profile_Name_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); 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 profile_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); profile_pane.setLayout(new BorderLayout()); profile_pane.add(profile_label, BorderLayout.CENTER); name_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,5)); name_pane.setLayout(new BorderLayout(5,0)); name_pane.add(name_label, BorderLayout.WEST); name_pane.add(name_field, BorderLayout.CENTER); center_pane.setLayout(new GridLayout(2,1,0,0)); center_pane.add(profile_pane); center_pane.add(name_pane); 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((Configuration.screen_size.width - ADD_FILE_SIZE.width) / 2, (Configuration.screen_size.height - ADD_FILE_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) { String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM); // Ensure that this source doesn't already exist. if(!Gatherer.c_man.msm.profiler.containsSource(name_str)) { // Add source with empty hashmap of actions. Gatherer.c_man.msm.profiler.addSource(name_str); // Add to tree model.add(model.getProfileNode(), name_str, MEMNode.COLLECTION); setVisible(false); } // Otherwise warn the user and don't hide the prompt. else { JOptionPane.showMessageDialog(self, Dictionary.get("MEM.File_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } name_str = null; } else if(source == cancel_button) { setVisible(false); } else { name_field.setText(""); setVisible(true); } source = null; } public void dispose() { cancel_button = null; ok_button = null; name_field = null; ///ystem.err.println("Dispose AddFileActionListener"); 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; public AddSetActionListener() { super(self); setModal(true); setSize(ADD_SET_SIZE); Dictionary.setText(this, "MEM.AddSet"); // Creation JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(Configuration.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, "MEM.Namespace"); namespace_field = TransformCharacterTextField.createNamespaceTextField(); namespace_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); namespace_field.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); namespace_field.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); namespace_field.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(namespace_field, "MEM.Set_Namespace_Tooltip"); JLabel name_label = new JLabel(); name_label.setOpaque(false); Dictionary.setText(name_label, "MEM.Name"); name_field = new JTextField(); name_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); name_field.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); name_field.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); name_field.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(name_field, "MEM.Set_Name_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); 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,0,5)); label_pane.add(name_label); label_pane.add(namespace_label); boxes_pane.setLayout(new GridLayout(2,1,0,5)); 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((Configuration.screen_size.width - ADD_SET_SIZE.width) / 2, (Configuration.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) { String namespace_str = namespace_field.getText(); String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM); // Ensure the set doesn't already exist if(Gatherer.c_man.msm.getSet(name_str) == null) { MetadataSet set = Gatherer.c_man.msm.addSet(namespace_str, name_str); // Update tree. model.add(null, set, MEMNode.SET); // Done set = null; setVisible(false); } // Otherwise show a warning. else { JOptionPane.showMessageDialog(self, Dictionary.get("MEM.Set_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } name_str = null; namespace_str = null; } else if(source == cancel_button) { setVisible(false); } else { name_field.setText(""); setVisible(true); } } public void dispose() { cancel_button = null; ok_button = null; name_field = null; ///ystem.err.println("Dispose AddSetActionListener"); super.dispose(); } } private class AddOrEditValueActionListener extends ModalDialog implements ActionListener, TreeSelectionListener { private boolean add_type = true; private boolean ignore = false; private GValueNode subject_node = null; private JButton cancel_button = null; private JButton ok_button = null; private JTextArea value = null; private SmarterTree subject_tree = null; /** Constructor. */ public AddOrEditValueActionListener() { super(self); this.setModal(true); this.setSize(ADD_OR_EDIT_VALUE_SIZE); // Create JPanel content_pane = (JPanel) getContentPane(); content_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false)); JPanel center_pane = new JPanel(); center_pane.setOpaque(false); JPanel inner_pane = new JPanel(); inner_pane.setOpaque(false); JPanel subject_tree_pane = new JPanel(); subject_tree_pane.setOpaque(false); JLabel subject_tree_label = new JLabel(); subject_tree_label.setOpaque(false); Dictionary.setText(subject_tree_label, "MEM.Subject"); subject_tree = new SmarterTree(); subject_tree.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); subject_tree.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); subject_tree.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); subject_tree.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); JPanel value_pane = new JPanel(); value_pane.setOpaque(false); JLabel value_label = new JLabel(); value_label.setOpaque(false); Dictionary.setText(value_label, "MEM.Value"); value = new JTextArea(); value.setBackground(Configuration.getColor("coloring.collection_tree_background", false)); value.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); value.setSelectionColor(Configuration.getColor("coloring.collection_selection_background", false)); value.setSelectedTextColor(Configuration.getColor("coloring.collection_selection_foreground", false)); Dictionary.setTooltip(value, "MEM.Value_Tooltip"); JPanel button_pane = new JPanel(); button_pane.setOpaque(false); ok_button = new GLIButton(); ok_button.setMnemonic(KeyEvent.VK_O); ok_button.setEnabled(false); 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); // Connect ok_button_enabler.add(value); cancel_button.addActionListener(this); ok_button.addActionListener(this); subject_tree.addTreeSelectionListener(this); // Layout subject_tree_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); subject_tree_pane.setLayout(new BorderLayout()); subject_tree_pane.add(subject_tree_label, BorderLayout.NORTH); subject_tree_pane.add(new JScrollPane(subject_tree), BorderLayout.CENTER); value_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); value_pane.setLayout(new BorderLayout()); value_pane.add(value_label, BorderLayout.NORTH); value_pane.add(new JScrollPane(value), BorderLayout.CENTER); inner_pane.setLayout(new GridLayout(2,1)); inner_pane.add(subject_tree_pane); inner_pane.add(value_pane); button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); button_pane.setLayout(new GridLayout(1,2,5,5)); button_pane.add(ok_button); button_pane.add(cancel_button); content_pane.setLayout(new BorderLayout()); content_pane.add(inner_pane, BorderLayout.CENTER); content_pane.add(button_pane, BorderLayout.SOUTH); setLocation((Configuration.screen_size.width - ADD_OR_EDIT_VALUE_SIZE.width) / 2, (Configuration.screen_size.height - ADD_OR_EDIT_VALUE_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 add a new metadata value to the assigned values tree. * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if(source == ok_button) { String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM); // Now we action as necessary GValueModel model = Gatherer.c_man.msm.getValueTree(current_element); if(add_type) { ///ystem.err.println("Add type - insert node: " + value.getText() + " into " + subject_node); // Add this value to the tree. model.addValue(value_str, subject_node); } else { // Rewrite this value in the DOM model. Note that this will automatically rewrite all assignments as they are live references. current_value_node.setValue(value_str); // Now insert the node into the currently selected subject, but only if the parent has changed. if(subject_node != current_value_node.getParent()) { GValueNode old_subject_node = (GValueNode) current_value_node.getParent(); // Find the new values position in subject_nodes children. GValueNode sibling = null; int index = 0; boolean found = false; while(index < subject_node.getChildCount() && !found) { sibling = (GValueNode) subject_node.getChildAt(index); int order = current_value_node.toString().compareToIgnoreCase(sibling.toString()); // If the sibling is 'greater than' or comes after current value then insert. if(order < 0) { // Insert. This will coincidently remove from original parent. Node parent_node = subject_node.getElement(); Node child_node = current_value_node.getElement(); Node sibling_node = sibling.getElement(); parent_node.insertBefore(child_node, sibling_node); found = true; } // The value already exists exactly as is. In theory this case can never happenm but just incase do nothing more. else if(order == 0) { found = true; } // The sibling is 'less than' or before the current value, keep looking. else { index++; } } // If we haven't done so yet, insert the current node. This will coincidently remove from original parent. if(!found) { Node parent_node = subject_node.getElement(); Node child_node = current_value_node.getElement(); parent_node.appendChild(child_node); } // Inform the tree model what two nodes structures have changed (origin and destination). //subject_node.unmap(); //old_subject_node.unmap(); model.nodeStructureChanged(old_subject_node); model.nodeStructureChanged(subject_node); } // And if a data change was made tell the tree its data model is ka-bluey. else { model.nodeChanged(current_value_node); } } model = null; // Hide dialog setVisible(false); } else if(source == cancel_button) { // Hide dialog setVisible(false); } else { // Reset dialog // current_value_node GValueModel model = Gatherer.c_man.msm.getValueTree(current_element); subject_tree.setModel(model); // Task specific if(source == add_value) { add_type = true; if(current_value_node != null) { subject_node = current_value_node; } else { subject_node = (GValueNode) model.getRoot(); } value.setText(""); Dictionary.setText(this, "MEM.AddValue"); } else { add_type = false; if(current_value_node != null) { subject_node = (GValueNode) current_value_node.getParent(); } else { subject_node = (GValueNode) model.getRoot(); } value.setText(Codec.transform(current_value_node.toString(), Codec.DOM_TO_TEXT)); Dictionary.setText(this, "MEM.EditValue"); } model = null; if(subject_node != null) { TreePath path = new TreePath(subject_node.getPath()); subject_tree.scrollPathToVisible(path); subject_tree.setSelectionPath(path); path = null; } // Display setVisible(true); } } public void dispose() { cancel_button = null; ok_button = null; subject_node = null; subject_tree = null; value = null; ///ystem.err.println("Dispose AddOrEditValueActionListener"); super.dispose(); } public void valueChanged(TreeSelectionEvent event) { if(subject_tree.getSelectionCount() > 0 && !ignore) { ignore = true; TreePath selected_path = subject_tree.getSelectionPath(); GValueNode requested_node = (GValueNode) selected_path.getLastPathComponent(); // Ensure the requested node is not a descendant of the current_value_node if(current_value_node != null) { if(!add_type && current_value_node.isNodeDescendant(requested_node)) { TreePath path = new TreePath(subject_node.getPath()); subject_tree.scrollPathToVisible(path); subject_tree.setSelectionPath(path); } else { subject_node = requested_node; } } selected_path = null; ignore = false; } } } private class CloseActionListener extends ModalDialog 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 close the editor dialog. * @param event An ActionEvent containing information about the event. */ public void actionPerformed(ActionEvent event) { // I don't know why this is causing a problem even after the dialog has been disposed, but it is. GValueModel value_model = Gatherer.c_man.msm.getValueTree(current_element); if (value_model != null) { value_model.removeTreeModelListener(keep_root_expanded_listener); } self.dispose(); } } /** This listener is responsible for keeping the root node of a value tree expanded where and when possible. */ private class KeepTreeRootExpandedListener implements TreeModelListener { /** Invoked after a node (or a set of siblings) has changed in some way. */ public void treeNodesChanged(TreeModelEvent e) { } /** Invoked after nodes have been inserted into the tree. */ public void treeNodesInserted(TreeModelEvent e) { if(element_values != null && element_values.getModel() != null && element_values.getModel().getRoot() != null) { element_values.expandPath(new TreePath(element_values.getModel().getRoot())); } } /** Invoked after nodes have been removed from the tree. */ public void treeNodesRemoved(TreeModelEvent e) { } /** Invoked after the tree has drastically changed structure from a given node down. */ public void treeStructureChanged(TreeModelEvent e) { element_values.expandPath(new TreePath(element_values.getModel().getRoot())); } } private class RemoveAttributeActionListener 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_attribute != -1) { int result = JOptionPane.showOptionDialog(self, Dictionary.get("MEM.Confirm_Removal", Dictionary.get("MEM.Attribute")), Dictionary.get("MEM.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 a collection file been selected... if(current_collection_file != null) { // Remove a profile String source = (String) profile_attributes.getValueAt(current_attribute, 0); Gatherer.c_man.msm.profiler.removeAction(current_collection_file, source); source = null; // Refresh table ((AttributeTableModel)profile_attributes.getModel()).removeRow(current_attribute); } // or has an element been selected else 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); } // Disable buttons edit_attribute.setEnabled(false); remove_attribute.setEnabled(false); ignore = false; } } } } 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("MEM.Confirm_Removal", Dictionary.get("MEM.Element")), Dictionary.get("MEM.Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]); // Remove this attribute if(result == 0) { ignore = true; Gatherer.c_man.msm.removeElement(current_element); // Clear selection mds_tree.clearSelection(); model.remove(current_element.toString(), MEMNode.ELEMENT); // Meanwhile disable/enable controls given we had an element selected, but no longer do. remove_element.setEnabled(false); // Show a blank panel. card_layout.show(details_pane, BLANK); ignore = false; } } else { ///ystem.err.println("No current element selected."); } } } private class RemoveFileActionListener 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_collection_file != null) { int result = JOptionPane.showOptionDialog(self, Dictionary.get("MEM.Confirm_Removal", Dictionary.get("MEM.File")), Dictionary.get("MEM.Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]); // Remove the current collection file profile from the profiler. if(result == 0) { ignore = true; Gatherer.c_man.msm.profiler.removeProfile(current_collection_file); // Clear selection mds_tree.clearSelection(); model.remove(current_collection_file, MEMNode.COLLECTION); // Meanwhile disable/enable controls given we had a set selected, but no longer do. remove_file.setEnabled(false); // Show a blank panel. card_layout.show(details_pane, BLANK); ignore = false; } } } } 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) { int result = JOptionPane.showOptionDialog(self, Dictionary.get("MEM.Confirm_Removal", Dictionary.get("MEM.Set")), Dictionary.get("MEM.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; Gatherer.c_man.msm.removeSet(current_set); // Clear selection mds_tree.clearSelection(); model.remove(current_set.toString(), MEMNode.SET); // Meanwhile disable/enable controls given we had a set selected, but no longer do. remove_set.setEnabled(false); // Show a blank panel. card_layout.show(details_pane, BLANK); ignore = false; } } } } /** This class will remove the currently selected metadata or profile value when any registered control is actioned. Note that removing a value acts differently from the other removes in that if you remove a value which is still assigned somewhere the values are restored next time said assignment is viewed. This turned out far easier and reasonable to code than attempting to remove all remaining values when you delete its reference in the GValueModel. */ private class RemoveValueActionListener 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_value_node != null) { int result = JOptionPane.showOptionDialog(self, Dictionary.get("MEM.Confirm_Removal", Dictionary.get("MEM.Value")), Dictionary.get("MEM.Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]); // Remove the current selected value if(result == 0) { ignore = true; GValueModel model = (GValueModel) element_values.getModel(); model.removeValue(current_value_node); // Meanwhile disable/enable controls given we had a value selected, but no longer do. edit_value.setEnabled(false); remove_value.setEnabled(false); 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()) { if((current_attribute = table.getSelectedRow()) != -1) { edit_attribute.setEnabled(true); remove_attribute.setEnabled(true); } else { current_attribute = -1; edit_attribute.setEnabled(false); remove_attribute.setEnabled(false); } } } } private class ElementValuesTreeSelectionListener implements TreeSelectionListener { public void valueChanged(TreeSelectionEvent event) { if(element_values.getSelectionCount() > 0) { // Retrieve the selected value node. TreePath selected_path = element_values.getSelectionPath(); current_value_node = (GValueNode) selected_path.getLastPathComponent(); edit_value.setEnabled(true); remove_value.setEnabled(true); } else { current_value_node = null; edit_value.setEnabled(false); remove_value.setEnabled(false); } } } private class MDSTreeSelectionListener implements TreeSelectionListener { public void valueChanged(TreeSelectionEvent event) { if(!ignore) { // Clear all variables based on previous tree selection current_collection_file = null; current_element = null; current_set = null; // Now process the node selected TreePath path = event.getPath(); current_node = (MEMNode)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 MEMNode.COLLECTION: current_collection_file = (String) current_node.getUserObject(); atm = current_node.getModel(); if(atm == null) { ArrayList sources = Gatherer.c_man.msm.profiler.getSources(current_collection_file); attributes = new TreeSet(); for(int i = 0; i < sources.size(); i++) { String source = (String) sources.get(i); String action = Gatherer.c_man.msm.profiler.getAction(current_collection_file, source); if (action == null) { action = Dictionary.get("MEM.Ignore"); } attributes.add(new Attribute(source, action)); } atm = new AttributeTableModel(attributes, Dictionary.get("MEM.Source"), Dictionary.get("MEM.Target"), Dictionary.get("MEM.Ignore")); //current_node.setModel(atm); } profile_attributes.setModel(atm); atm.setScrollPane(profile_attributes_scroll); atm.setTable(profile_attributes); card_layout.show(details_pane, PROFILE); setControls(true, false, false, true, false, false, true, false, false, false, false, false); break; case MEMNode.ELEMENT: current_element = current_node.getElement(); atm = current_node.getModel(); if(atm == null) { atm = new AttributeTableModel(current_element.getAttributes(), Dictionary.get("MEM.Name"), Dictionary.get("MEM.Language_Code"), Dictionary.get("MEM.Value"), ""); //current_node.setModel(atm); } element_attributes.setModel(atm); atm.setScrollPane(element_attributes_scroll); atm.setTable(element_attributes); // Be careful not to add the keep_root_expanded_listener over and over! GValueModel value_model = Gatherer.c_man.msm.getValueTree(current_element); if(value_model != null) { value_model.removeTreeModelListener(keep_root_expanded_listener); // Remove it if its already there value_model.addTreeModelListener(keep_root_expanded_listener); // Then add again. element_values.setModel(value_model); element_values_layout.show(element_values_pane, VALUES); // Meanwhile disable/enable controls depending on this Element selection. setControls(true, false, false, false, false, true, true, false, false, true, false, false); } else { element_values_layout.show(element_values_pane, BLANK); // Meanwhile disable/enable controls depending on this Element selection. setControls(true, false, false, false, false, false, true, false, false, false, false, false); } card_layout.show(details_pane, ELEMENT); break; case MEMNode.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("MEM.Name"), Dictionary.get("MEM.Value"), ""); //current_node.setModel(atm); temp = null; } set_attributes.setModel(atm); atm.setScrollPane(set_attributes_scroll); atm.setTable(set_attributes); card_layout.show(details_pane, SET); attributes = null; // Meanwhile disable/enable controls depending on this Element selection. setControls(true, true, false, false, true, false, true, false, false, false, false, false); break; case MEMNode.PROFILER: // Meanwhile disable/enable controls depending on this Element selection. setControls(true, false, true, false, false, false, false, false, false, false, false, false); default: // Show a blank panel. card_layout.show(details_pane, BLANK); } attributes = null; path = null; atm = null; } } } private class MEMTreeCellRenderer 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; } } /** 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(); } } }