source: trunk/gli/src/org/greenstone/gatherer/mem/MetadataEditorManager.java@ 7156

Last change on this file since 7156 was 7156, checked in by kjdon, 20 years ago

fixed some more static label sizes and deleted a lot of commented out stuff

  • Property svn:keywords set to Author Date Id Revision
File size: 84.1 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.mem;
38
39import java.awt.*;
40import java.awt.event.*;
41import java.util.*;
42import javax.swing.*;
43import javax.swing.event.*;
44import javax.swing.text.*;
45import javax.swing.tree.*;
46import org.greenstone.gatherer.Dictionary;
47import org.greenstone.gatherer.Gatherer;
48import org.greenstone.gatherer.cdm.LanguageListCellRenderer;
49import org.greenstone.gatherer.gui.ComboArea;
50import org.greenstone.gatherer.gui.GComboBox;
51import org.greenstone.gatherer.gui.GLIButton;
52import org.greenstone.gatherer.gui.SmarterTable;
53import org.greenstone.gatherer.gui.SmarterTree;
54import org.greenstone.gatherer.gui.SimpleMenuBar;
55import org.greenstone.gatherer.gui.ModalDialog;
56import org.greenstone.gatherer.gui.NonWhitespaceField;
57import org.greenstone.gatherer.gui.TransformCharacterTextField;
58import org.greenstone.gatherer.mem.Attribute;
59import org.greenstone.gatherer.mem.AttributeTableModel;
60import org.greenstone.gatherer.mem.MEMNode;
61import org.greenstone.gatherer.msm.ElementWrapper;
62import org.greenstone.gatherer.msm.MetadataSet;
63import org.greenstone.gatherer.util.Codec;
64import org.greenstone.gatherer.util.Utility;
65import org.greenstone.gatherer.valuetree.GValueModel;
66import org.greenstone.gatherer.valuetree.GValueNode;
67import org.w3c.dom.*;
68
69/** 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.
70 * @author John Thompson, Greenstone Digital Library, University of Waikato
71 * @version 2.3b
72 */
73public class MetadataEditorManager
74 extends ModalDialog {
75 static final public int ADD_SET = 0;
76 static final public int NORMAL = 1;
77 static final public int REMOVE_SET = 2;
78 /** The default size of the editor dialog. */
79 static final private Dimension ADD_ELEMENT_SIZE = new Dimension(400,125);
80 static final private Dimension ADD_FILE_SIZE = new Dimension(400,125);
81 static final private Dimension ADD_SET_SIZE = new Dimension(400,125);
82 static final private Dimension ADD_OR_EDIT_ATTRIBUTE_SIZE = new Dimension(600,325);
83 static final private Dimension ADD_OR_EDIT_VALUE_SIZE = new Dimension(600,440);
84 static final private Dimension COMPONENT_SIZE = new Dimension(300,30);
85 static final private Dimension SIZE = new Dimension(800,480);
86 static final private String BLANK = "blank";
87 static final private String ELEMENT = "element";
88 static final private String PROFILE = "profile";
89 static final private String SET = "set";
90 static final private String VALUES = "values";
91
92 private AddElementActionListener add_element_action_listener = null;
93 private AddFileActionListener add_file_action_listener = null;
94 private AddSetActionListener add_set_action_listener = null;
95 /** The class used to handle add or edit attribute actions has to be globally available so that we can dispose of its dialog properly. */
96 private AddOrEditAttributeActionListener add_or_edit_attribute_action_listener = null;
97 /** The class used to handle add or edit value actions has to be globally available so that we can dispose of its dialog properly. */
98 private AddOrEditValueActionListener add_or_edit_value_action_listener = null;
99 private boolean ignore = false;
100 /** A card layout is used to switch between the two differing detail views. */
101 private CardLayout card_layout = null;
102 /** A card layout is used to switch between a value tree or an empty placeholder (if no value tree available). */
103 private CardLayout element_values_layout = null;
104 /** Um, the size of the screen I'd guess. */
105 private Dimension screen_size = null;
106 private ElementWrapper current_element = null;
107 private GValueNode current_value_node = null;
108 /** A reference to ourselves so our inner classes can dispose of us. */
109 private MetadataEditorManager self = null;
110 private int current_attribute = -1;
111 private int current_attribute_type = -1;
112 private JButton add_attribute = null;
113 private JButton add_element = null;
114 private JButton add_file = null;
115 private JButton add_set = null;
116 private JButton add_value = null;
117 private JButton close = null;
118 private JButton edit_attribute = null;
119 private JButton edit_value = null;
120 private JButton remove_attribute = null;
121 private JButton remove_element = null;
122 private JButton remove_file = null;
123 private JButton remove_set = null;
124 private JButton remove_value = null;
125 private JLabel element_name = null;
126 private JLabel profile_name = null;
127 private JLabel set_name = null;
128 private JScrollPane element_attributes_scroll = null;
129 private JScrollPane profile_attributes_scroll = null;
130 private JScrollPane set_attributes_scroll = null;
131 private JPanel details_pane = null;
132 private JPanel element_values_pane = null;
133 private KeepTreeRootExpandedListener keep_root_expanded_listener = null;
134 private MEMModel model = null;
135 private MEMNode current_node = null;
136 private MetadataSet current_set = null;
137 private Object target = null;
138 private RemoveSetActionListener remove_set_action_listener;
139 private SmarterTable element_attributes = null;
140 private SmarterTable profile_attributes = null;
141 private SmarterTable set_attributes = null;
142 private SmarterTree element_values = null;
143 /** A tree that represents the current metadata sets associated with this collection. */
144 private SmarterTree mds_tree = null;
145 private String current_collection_file = null;
146 private String dialog_options[] = null;
147
148 /** Constructor.
149 * @param set a MetadataSet that should be initially selected
150 * @param action a systematic action that should be performed
151 */
152 public MetadataEditorManager(MetadataSet set, int action) {
153 super(Gatherer.g_man);
154 this.dialog_options = new String[2];
155 this.screen_size = Gatherer.config.screen_size;
156 this.self = this;
157
158 dialog_options[0] = Dictionary.get("General.OK");
159 dialog_options[1] = Dictionary.get("General.Cancel");
160
161 // Creation
162 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
163 setModal(true);
164 setSize(SIZE);
165 setJMenuBar(new SimpleMenuBar("editingmetadatasets"));
166 Dictionary.setText(this, "MEM.Title");
167
168 JPanel content_pane = (JPanel) getContentPane();
169 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
170
171 JPanel upper_pane = new JPanel();
172 upper_pane.setOpaque(false);
173
174 model = new MEMModel();
175
176 JPanel mds_tree_pane = new JPanel();
177 mds_tree_pane.setOpaque(false);
178 mds_tree_pane.setPreferredSize(new Dimension(200,500));
179 mds_tree = new SmarterTree(model);
180 mds_tree.setCellRenderer(new MEMTreeCellRenderer());
181 mds_tree.setRootVisible(false);
182 mds_tree.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
183 mds_tree.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
184 mds_tree.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
185 mds_tree.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
186 // We may have been asked to select a cetain initial set
187 if(set != null) {
188 MEMNode root = (MEMNode) model.getRoot();
189 for(int i = 0; i < root.getChildCount(); i++) {
190 MEMNode child = (MEMNode) root.getChildAt(i);
191 if(set.equals(child.getUserObject())) {
192 TreePath path = new TreePath(child.getPath());
193 mds_tree.setSelectionPath(path);
194 mds_tree.expandPath(path);
195 path = null;
196 }
197 child = null;
198 }
199 root = null;
200 }
201
202 details_pane = new JPanel();
203 details_pane.setOpaque(false);
204 card_layout = new CardLayout();
205
206 JPanel set_details_pane = new JPanel();
207 set_details_pane.setOpaque(false);
208
209 JPanel set_name_pane = new JPanel();
210 set_name_pane.setOpaque(false);
211 JLabel set_name_label = new JLabel();
212 set_name_label.setOpaque(false);
213 Dictionary.setText(set_name_label, "MEM.Name");
214 set_name = new JLabel();
215 set_name.setBorder(BorderFactory.createLoweredBevelBorder());
216 set_name.setOpaque(false);
217
218 JPanel set_attributes_pane = new JPanel();
219 set_attributes_pane.setOpaque(false);
220 set_attributes_scroll = new JScrollPane();
221 set_attributes_scroll.getViewport().setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
222 set_attributes_scroll.setOpaque(true);
223 set_attributes = new SmarterTable();
224 set_attributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
225 set_attributes.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
226 set_attributes.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
227 set_attributes.setHeadingBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
228 set_attributes.setHeadingForeground(Gatherer.config.getColor("coloring.collection_heading_foreground", false));
229 set_attributes.setOpaque(false);
230 set_attributes.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
231 set_attributes.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
232 set_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
233
234 JPanel element_details_pane = new JPanel();
235 element_details_pane.setOpaque(false);
236
237 JPanel element_name_pane = new JPanel();
238 element_name_pane.setOpaque(false);
239 JLabel element_name_label = new JLabel();
240 element_name_label.setOpaque(false);
241 Dictionary.setText(element_name_label, "MEM.Name");
242 element_name = new JLabel();
243 element_name.setBorder(BorderFactory.createLoweredBevelBorder());
244 element_name.setOpaque(false);
245
246 JPanel element_inner_pane = new JPanel();
247 element_inner_pane.setOpaque(false);
248
249 JPanel element_attributes_pane = new JPanel();
250 element_attributes_pane.setOpaque(false);
251 element_attributes_scroll = new JScrollPane();
252 element_attributes_scroll.getViewport().setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
253 element_attributes_scroll.setOpaque(true);
254 element_attributes = new SmarterTable();
255 element_attributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
256 element_attributes.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
257 element_attributes.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
258 element_attributes.setHeadingBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
259 element_attributes.setHeadingForeground(Gatherer.config.getColor("coloring.collection_heading_foreground", false));
260 element_attributes.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
261 element_attributes.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
262 element_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
263
264 element_values_layout = new CardLayout();
265 element_values_pane = new JPanel();
266 element_values_pane.setOpaque(false);
267 element_values = new SmarterTree();
268 element_values.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
269 element_values.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
270 element_values.setRootVisible(false);
271 element_values.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
272 element_values.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
273
274 JPanel element_novalues_pane = new JPanel();
275
276 keep_root_expanded_listener = new KeepTreeRootExpandedListener();
277
278 JPanel profile_details_pane = new JPanel();
279 profile_details_pane.setOpaque(false);
280 JPanel profile_name_pane = new JPanel();
281 profile_name_pane.setOpaque(false);
282 JLabel profile_name_label = new JLabel();
283 profile_name_label.setOpaque(false);
284 Dictionary.setText(profile_name_label, "MEM.Name");
285 profile_name = new JLabel();
286 profile_name.setBorder(BorderFactory.createLoweredBevelBorder());
287 profile_name.setOpaque(false);
288
289 JPanel profile_attributes_pane = new JPanel();
290 profile_attributes_pane.setOpaque(false);
291 profile_attributes_scroll = new JScrollPane();
292 profile_attributes_scroll.getViewport().setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
293 profile_attributes_scroll.setOpaque(true);
294 profile_attributes = new SmarterTable();
295 profile_attributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
296 profile_attributes.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
297 profile_attributes.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
298 profile_attributes.setHeadingBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
299 profile_attributes.setHeadingForeground(Gatherer.config.getColor("coloring.collection_heading_foreground", false));
300 profile_attributes.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
301 profile_attributes.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
302 profile_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
303
304 JPanel button_pane = new JPanel();
305 button_pane.setOpaque(false);
306
307 JPanel button_label_pane = new JPanel();
308 button_label_pane.setOpaque(false);
309
310 JLabel attribute_label = new JLabel();
311 attribute_label.setOpaque(false);
312 Dictionary.setText(attribute_label, "MEM.Attribute");
313
314 JLabel element_label = new JLabel();
315 element_label.setOpaque(false);
316 Dictionary.setText(element_label, "MEM.Element");
317
318 JLabel file_label = new JLabel();
319 file_label.setOpaque(false);
320 Dictionary.setText(file_label, "MEM.File");
321
322 JLabel set_label = new JLabel();
323 set_label.setOpaque(false);
324 Dictionary.setText(set_label, "MEM.Set");
325
326 JLabel value_label = new JLabel();
327 value_label.setOpaque(false);
328 Dictionary.setText(value_label, "MEM.Value");
329
330 JPanel inner_button_pane = new JPanel();
331 inner_button_pane.setOpaque(false);
332 add_attribute = new GLIButton();
333 add_attribute.setMnemonic(KeyEvent.VK_4);
334 Dictionary.setBoth(add_attribute, "MEM.Add", "MEM.Add_Attribute_Tooltip");
335 add_element = new GLIButton();
336 add_element.setMnemonic(KeyEvent.VK_3);
337 Dictionary.setBoth(add_element, "MEM.Add", "MEM.Add_Element_Tooltip");
338 add_file = new GLIButton();
339 add_file.setMnemonic(KeyEvent.VK_2);
340 Dictionary.setBoth(add_file, "MEM.Add", "MEM.Add_File_Tooltip");
341 add_set = new GLIButton();
342 add_set.setMnemonic(KeyEvent.VK_1);
343 Dictionary.setBoth(add_set, "MEM.Add", "MEM.Add_Set_Tooltip");
344 add_value = new GLIButton();
345 add_value.setMnemonic(KeyEvent.VK_5);
346 Dictionary.setBoth(add_value, "MEM.Add", "MEM.Add_Value_Tooltip");
347
348 edit_attribute = new GLIButton();
349 edit_attribute.setMnemonic(KeyEvent.VK_6);
350 Dictionary.setBoth(edit_attribute, "MEM.Edit", "MEM.Edit_Attribute_Tooltip");
351 edit_value = new GLIButton();
352 edit_value.setMnemonic(KeyEvent.VK_7);
353 Dictionary.setBoth(edit_value, "MEM.Edit", "MEM.Edit_Value_Tooltip");
354
355 remove_attribute = new GLIButton();
356 remove_attribute.setMnemonic(KeyEvent.VK_MINUS);
357 Dictionary.setBoth(remove_attribute, "MEM.Remove", "MEM.Remove_Attribute_Tooltip");
358 remove_element = new GLIButton();
359 remove_element.setMnemonic(KeyEvent.VK_0);
360 Dictionary.setBoth(remove_element, "MEM.Remove", "MEM.Remove_Element_Tooltip");
361 remove_file = new GLIButton();
362 remove_file.setMnemonic(KeyEvent.VK_9);
363 Dictionary.setBoth(remove_file, "MEM.Remove", "MEM.Remove_File_Tooltip");
364 remove_set = new GLIButton();
365 remove_set.setMnemonic(KeyEvent.VK_8);
366 Dictionary.setBoth(remove_set, "MEM.Remove", "MEM.Remove_Set_Tooltip");
367 remove_value = new GLIButton();
368 remove_value.setMnemonic(KeyEvent.VK_EQUALS);
369 Dictionary.setBoth(remove_value, "MEM.Remove", "MEM.Remove_Value_Tooltip");
370 setControls(false, false, false, false, false, false, false, false, false, false, false, false);
371
372 close = new GLIButton();
373 close.setMnemonic(KeyEvent.VK_C);
374 Dictionary.setBoth(close, "General.Close", "General.Close_Tooltip");
375
376 add_element_action_listener = new AddElementActionListener();
377 add_file_action_listener = new AddFileActionListener();
378 add_set_action_listener = new AddSetActionListener();
379 add_or_edit_attribute_action_listener = new AddOrEditAttributeActionListener();
380 add_or_edit_value_action_listener = new AddOrEditValueActionListener();
381 remove_set_action_listener = new RemoveSetActionListener();
382
383 // Some blank panel
384 JPanel blank_pane = new JPanel();
385 blank_pane.setOpaque(false);
386 JPanel edit_file_pane = new JPanel();
387 edit_file_pane.setOpaque(false);
388 JPanel edit_element_pane = new JPanel();
389 edit_element_pane.setOpaque(false);
390 JPanel edit_set_pane = new JPanel();
391 edit_set_pane.setOpaque(false);
392
393 // Connection
394 add_attribute.addActionListener(add_or_edit_attribute_action_listener);
395 add_element.addActionListener(add_element_action_listener);
396 add_file.addActionListener(add_file_action_listener);
397 add_set.addActionListener(add_set_action_listener);
398 add_value.addActionListener(add_or_edit_value_action_listener);
399 close.addActionListener(new CloseActionListener());
400 edit_attribute.addActionListener(add_or_edit_attribute_action_listener);
401 edit_value.addActionListener(add_or_edit_value_action_listener);
402 remove_attribute.addActionListener(new RemoveAttributeActionListener());
403 remove_element.addActionListener(new RemoveElementActionListener());
404 remove_file.addActionListener(new RemoveFileActionListener());
405 remove_set.addActionListener(remove_set_action_listener);
406 remove_value.addActionListener(new RemoveValueActionListener());
407 element_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(element_attributes));
408 profile_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(profile_attributes));
409 set_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(set_attributes));
410 element_values.addTreeSelectionListener(new ElementValuesTreeSelectionListener());
411 mds_tree.addTreeSelectionListener(new MDSTreeSelectionListener());
412 // Layout
413 mds_tree_pane.setLayout(new BorderLayout());
414 mds_tree_pane.add(new JScrollPane(mds_tree), BorderLayout.CENTER);
415
416 set_name_pane.setLayout(new BorderLayout());
417 set_name_pane.add(set_name_label, BorderLayout.WEST);
418 set_name_pane.add(set_name, BorderLayout.CENTER);
419
420 set_attributes_scroll.setViewportView(set_attributes);
421
422 set_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Attributes")), BorderFactory.createEmptyBorder(2,2,2,2)));
423 set_attributes_pane.setLayout(new BorderLayout());
424 set_attributes_pane.add(set_attributes_scroll, BorderLayout.CENTER);
425
426 set_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Set_Details")), BorderFactory.createEmptyBorder(2,2,2,2)));
427 set_details_pane.setLayout(new BorderLayout());
428 //set_details_pane.add(set_name_pane, BorderLayout.NORTH);
429 set_details_pane.add(set_attributes_pane, BorderLayout.CENTER);
430
431 element_name_pane.setLayout(new BorderLayout());
432 element_name_pane.add(element_name_label, BorderLayout.WEST);
433 element_name_pane.add(element_name, BorderLayout.CENTER);
434
435 element_attributes_scroll.setViewportView(element_attributes);
436
437 element_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Attributes")), BorderFactory.createEmptyBorder(2,2,2,2)));
438 element_attributes_pane.setLayout(new BorderLayout());
439 element_attributes_pane.add(element_attributes_scroll, BorderLayout.CENTER);
440
441 element_values_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Values")), BorderFactory.createEmptyBorder(2,2,2,2)));
442 //element_values_pane.setLayout(new BorderLayout());
443 //element_values_pane.add(new JScrollPane(element_values), BorderLayout.CENTER);
444 element_values_pane.setLayout(element_values_layout);
445 element_values_pane.add(element_novalues_pane, BLANK);
446 element_values_pane.add(new JScrollPane(element_values), VALUES);
447
448 element_inner_pane.setLayout(new GridLayout(2,1));
449 element_inner_pane.add(element_attributes_pane);
450 element_inner_pane.add(element_values_pane);
451
452 element_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Element_Details")), BorderFactory.createEmptyBorder(2,2,2,2)));
453 element_details_pane.setLayout(new BorderLayout());
454 //element_details_pane.add(element_name_pane, BorderLayout.NORTH);
455 element_details_pane.add(element_inner_pane, BorderLayout.CENTER);
456
457 profile_name_pane.setLayout(new BorderLayout());
458 profile_name_pane.add(profile_name_label, BorderLayout.WEST);
459 profile_name_pane.add(profile_name, BorderLayout.CENTER);
460
461 profile_attributes_scroll.setViewportView(profile_attributes);
462
463 profile_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Profiles")), BorderFactory.createEmptyBorder(2,2,2,2)));
464 profile_attributes_pane.setLayout(new BorderLayout());
465 profile_attributes_pane.add(profile_attributes_scroll, BorderLayout.CENTER);
466
467 profile_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("MEM.Profile_Details")), BorderFactory.createEmptyBorder(2,2,2,2)));
468 profile_details_pane.setLayout(new BorderLayout());
469 //profile_details_pane.add(profile_name_pane, BorderLayout.NORTH);
470 profile_details_pane.add(profile_attributes_pane, BorderLayout.CENTER);
471
472 details_pane.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
473 details_pane.setLayout(card_layout);
474 details_pane.add(blank_pane, BLANK);
475 details_pane.add(set_details_pane, SET);
476 details_pane.add(element_details_pane, ELEMENT);
477 details_pane.add(profile_details_pane, PROFILE);
478
479 upper_pane.setLayout(new BorderLayout());
480 upper_pane.add(mds_tree_pane, BorderLayout.WEST);
481 upper_pane.add(details_pane, BorderLayout.CENTER);
482
483 button_label_pane.setLayout(new GridLayout(5,1,0,2));
484 button_label_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,2));
485 button_label_pane.add(set_label);
486 button_label_pane.add(file_label);
487 button_label_pane.add(element_label);
488 button_label_pane.add(attribute_label);
489 button_label_pane.add(value_label);
490
491 inner_button_pane.setLayout(new GridLayout(5,3,0,2));
492 inner_button_pane.add(add_set);
493 inner_button_pane.add(edit_set_pane);
494 inner_button_pane.add(remove_set);
495 inner_button_pane.add(add_file);
496 inner_button_pane.add(edit_file_pane);
497 inner_button_pane.add(remove_file);
498 inner_button_pane.add(add_element);
499 inner_button_pane.add(edit_element_pane);
500 inner_button_pane.add(remove_element);
501 inner_button_pane.add(add_attribute);
502 inner_button_pane.add(edit_attribute);
503 inner_button_pane.add(remove_attribute);
504 inner_button_pane.add(add_value);
505 inner_button_pane.add(edit_value);
506 inner_button_pane.add(remove_value);
507
508 button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
509 button_pane.setLayout(new BorderLayout());
510 button_pane.add(button_label_pane, BorderLayout.WEST);
511 button_pane.add(inner_button_pane, BorderLayout.CENTER);
512 button_pane.add(close, BorderLayout.EAST);
513
514 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
515 content_pane.setLayout(new BorderLayout());
516 content_pane.add(upper_pane, BorderLayout.CENTER);
517 content_pane.add(button_pane, BorderLayout.SOUTH);
518
519 // 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.
520 if(action != NORMAL) {
521 ActionTask task = new ActionTask(action);
522 task.start();
523 }
524 // Display
525 setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
526 setVisible(true);
527 }
528
529 private class ActionTask
530 extends Thread {
531 private int action;
532 public ActionTask(int action) {
533 this.action = action;
534 }
535 public void run() {
536 boolean complete = false;
537 while(!complete) {
538 if(self.isVisible()) {
539 switch(action) {
540 case ADD_SET:
541 add_set_action_listener.actionPerformed(new ActionEvent(this, 0, "Blarg!"));
542 break;
543 case REMOVE_SET:
544 if(!mds_tree.isSelectionEmpty()) {
545 remove_set_action_listener.actionPerformed(new ActionEvent(this, 0, "Blarg!"));
546 }
547 break;
548 }
549 complete = true;
550 }
551 else {
552 try {
553 synchronized(this) {
554 wait(100);
555 }
556 }
557 catch(Exception exception) {
558 }
559 }
560 }
561 }
562 }
563
564 public void dispose() {
565 // Destructor
566 card_layout = null;
567 screen_size = null;
568 self = null;
569 add_attribute = null;
570 add_element = null;
571 add_file = null;
572 add_set = null;
573 add_value = null;
574 close = null;
575 edit_attribute = null;
576 edit_value = null;
577 remove_attribute = null;
578 remove_element = null;
579 remove_file = null;
580 remove_set = null;
581 remove_value = null;
582 details_pane = null;
583 element_attributes = null;
584 set_attributes = null;
585 element_name = null;
586 set_name = null;
587 element_values = null;
588 mds_tree = null;
589 target = null;
590
591 // Dispose of inner dialogs
592 if (add_element_action_listener != null) {
593 add_element_action_listener.dispose();
594 add_element_action_listener = null;
595 }
596 if (add_or_edit_attribute_action_listener != null) {
597 add_or_edit_attribute_action_listener.dispose();
598 add_or_edit_attribute_action_listener = null;
599 }
600 if (add_or_edit_value_action_listener != null) {
601 add_or_edit_value_action_listener.dispose();
602 add_or_edit_value_action_listener = null;
603 }
604 remove_set_action_listener = null;
605 super.dispose();
606 }
607
608
609 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) {
610 add_attribute.setEnabled(a_a);
611 add_element.setEnabled(a_e);
612 add_file.setEnabled(true); // Always true
613 add_set.setEnabled(true); // Always true
614 add_value.setEnabled(a_v);
615 edit_attribute.setEnabled(e_a);
616 edit_value.setEnabled(e_v);
617 remove_attribute.setEnabled(r_a);
618 remove_element.setEnabled(r_e);
619 remove_file.setEnabled(r_f);
620 remove_set.setEnabled(r_s);
621 remove_value.setEnabled(r_v);
622 }
623
624 private class AddOrEditAttributeActionListener
625 extends ModalDialog
626 implements ActionListener {
627 private boolean add_type = true;
628 private ComboArea value = null;
629 private JButton cancel_button = null;
630 private JButton ok_button = null;
631 private JComboBox language_box = null;
632 private GComboBox name = null;
633 private HashMap name_to_values = null;
634 private JLabel target = null;
635 /** Constructor. */
636 public AddOrEditAttributeActionListener() {
637 super(self);
638 setModal(true);
639 setSize(ADD_OR_EDIT_ATTRIBUTE_SIZE);
640 name_to_values = new HashMap();
641
642 // Creation
643 JPanel content_pane = (JPanel) getContentPane();
644 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
645 JPanel upper_pane = new JPanel();
646 upper_pane.setOpaque(false);
647
648 JPanel labels_pane = new JPanel();
649 JPanel boxes_pane = new JPanel();
650
651 JLabel target_label = new JLabel();
652 target_label.setOpaque(false);
653 Dictionary.setText(target_label, "MEM.Target");
654 target = new JLabel();
655 target.setOpaque(false);
656
657 JLabel name_label = new JLabel();
658 name_label.setOpaque(false);
659 Dictionary.setText(name_label, "MEM.Name");
660 name = new GComboBox();
661 name.setEditable(true);
662 Dictionary.setTooltip(name, "MEM.Attribute_Name_Tooltip");
663
664 JLabel language_label = new JLabel();
665 language_label.setOpaque(false);
666 Dictionary.setText(language_label, "MEM.Language");
667 language_box = new JComboBox(Gatherer.g_man.design_pane.getLanguageCodes().toArray());
668 language_box.setRenderer(new LanguageListCellRenderer());
669 Dictionary.setTooltip(language_box, "MEM.Attribute_Language_Tooltip");
670
671 JPanel center_pane = new JPanel();
672 center_pane.setOpaque(false);
673 value = new ComboArea(Dictionary.get("MEM.Values"), COMPONENT_SIZE);
674 value.setOpaque(false);
675
676 JTextArea v_text_area = (JTextArea) value.getTextComponent();
677 v_text_area.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
678 v_text_area.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
679 v_text_area.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
680 v_text_area.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
681 Dictionary.setTooltip(v_text_area, "MEM.Attribute_Value_Tooltip");
682
683 JPanel button_pane = new JPanel();
684 button_pane.setOpaque(false);
685 ok_button = new GLIButton();
686 ok_button.setMnemonic(KeyEvent.VK_O);
687 Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip");
688 cancel_button = new GLIButton();
689 cancel_button.setMnemonic(KeyEvent.VK_C);
690 Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip");
691
692 // Connection
693 TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
694 cancel_button.addActionListener(this);
695 name.addActionListener(this);
696 ok_button.addActionListener(this);
697 ok_button_enabler.add((JTextComponent)name.getEditor()); // Assuming the default editor is a JTextField!
698
699 // Layout
700 labels_pane.setLayout(new GridLayout(3,1,0,5));
701 labels_pane.add(target_label);
702 labels_pane.add(name_label);
703 labels_pane.add(language_label);
704
705 boxes_pane.setLayout(new GridLayout(3,1,0,5));
706 boxes_pane.add(target);
707 boxes_pane.add(name);
708 boxes_pane.add(language_box);
709
710 upper_pane.setLayout(new BorderLayout(5,0));
711 upper_pane.add(labels_pane, BorderLayout.WEST);
712 upper_pane.add(boxes_pane, BorderLayout.CENTER);
713
714 value.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
715
716 button_pane.setLayout(new GridLayout(1,2,5,0));
717 button_pane.add(ok_button);
718 button_pane.add(cancel_button);
719
720 center_pane.setLayout(new BorderLayout());
721 center_pane.add(value, BorderLayout.CENTER);
722 center_pane.add(button_pane, BorderLayout.SOUTH);
723
724 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
725 content_pane.setLayout(new BorderLayout());
726 content_pane.add(upper_pane, BorderLayout.NORTH);
727 content_pane.add(center_pane, BorderLayout.CENTER);
728
729 setLocation((Gatherer.config.screen_size.width - ADD_OR_EDIT_ATTRIBUTE_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_OR_EDIT_ATTRIBUTE_SIZE.height) / 2);
730 }
731 /** 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.
732 * @param event An <strong>ActionEvent</strong> containing information about the event.
733 */
734 public void actionPerformed(ActionEvent event) {
735 Object source = event.getSource();
736 if(source == ok_button) {
737 boolean success = true;
738 AttributeTableModel model;
739
740 // Add or edit a collect/set/element attribute
741 switch(current_attribute_type) {
742 case MEMNode.COLLECTION:
743 model = (AttributeTableModel) profile_attributes.getModel();
744 success = addOrEditCollectionAttribute(model);
745 break;
746 case MEMNode.SET:
747 model = (AttributeTableModel) set_attributes.getModel();
748 success = addOrEditSetAttribute(model);
749 break;
750 case MEMNode.ELEMENT:
751 model = (AttributeTableModel) element_attributes.getModel();
752 success = addOrEditElementAttribute(model);
753 break;
754 }
755
756 if (success) {
757 // Hide dialog
758 setVisible(false);
759 }
760 }
761 else if(source == cancel_button) {
762 // Hide dialog
763 setVisible(false);
764 }
765 else if(source == name) {
766 Object object = name.getSelectedItem();
767 if(object != null) {
768 java.util.List values = (java.util.List) name_to_values.get(object.toString());
769 if(values == null) { // Only for collection files, otherwise values != null && values.size() == 0
770 values = Gatherer.c_man.msm.getElements();
771 }
772 value.clear();
773 for(int i = 0; i < values.size(); i++) {
774 value.add(values.get(i));
775 }
776 }
777 }
778 else {
779 // Name combo box is enabled except when attributes are edited
780 //name.setEnabled((source != edit_attribute));
781 name_to_values.clear();
782 name.clear();
783 value.clear();
784 value.setText("");
785 // Build the correct name_to_values mapping
786 // Attributes are slightly tricky as they can come from several sources. Has a collection file been selected...
787 if(current_collection_file != null) {
788 target.setText(current_collection_file);
789 // Name is empty in this one, however values must be the current elements in the collection.
790 language_box.setEnabled(false);
791 }
792 // or has an element been selected
793 else if(current_element != null) {
794 target.setText(current_element.toString());
795 // Develop a model for name based on known attributes from all other elements.
796 java.util.List elements = Gatherer.c_man.msm.getElements();
797 for(int i = 0; i < elements.size(); i++) {
798 ElementWrapper element = (ElementWrapper) elements.get(i);
799 TreeSet attributes = element.getAttributes();
800 for(Iterator attribute_iterator = attributes.iterator(); attribute_iterator.hasNext(); ) {
801 Attribute attribute = (Attribute) attribute_iterator.next();
802 java.util.List values = (java.util.List) name_to_values.get(attribute.name);
803 if(values == null) {
804 values = new ArrayList();
805 name_to_values.put(attribute.name, values);
806 }
807 if(!values.contains(attribute.value)) {
808 values.add(attribute.value);
809 }
810 values = null;
811 attribute = null;
812 }
813 attributes = null;
814 element = null;
815 }
816 elements = null;
817 language_box.setEnabled(true);
818 }
819 else if(current_set != null) {
820 target.setText(current_set.toString());
821 // 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.
822 java.util.List sets = Gatherer.c_man.msm.getSets();
823 for(int i = 0; i < sets.size(); i++) {
824 MetadataSet set = (MetadataSet) sets.get(i);
825 NamedNodeMap attributes = set.getAttributes();
826 for(int j = 0; j < attributes.getLength(); j++) {
827 Attr attribute = (Attr) attributes.item(j);
828 String name_str = attribute.getName();
829 String value_str = attribute.getValue();
830 java.util.List values = (java.util.List) name_to_values.get(name_str);
831 if(values == null) {
832 values = new ArrayList();
833 name_to_values.put(name_str, values);
834 }
835 if(!values.contains(value_str)) {
836 values.add(value_str);
837 }
838 values = null;
839 value_str = null;
840 name_str = null;
841 attribute = null;
842 }
843 attributes = null;
844 set = null;
845 language_box.setEnabled(false);
846 }
847 sets = null;
848 // If this is an add remove all the attributes already present in the current set.
849 if(source == add_attribute) {
850 name.setEnabled(true);
851 NamedNodeMap attributes = current_set.getAttributes();
852 for(int i = 0; i < attributes.getLength(); i++) {
853 Attr attribute = (Attr) attributes.item(i);
854 String name_str = attribute.getName();
855 name_to_values.remove(name_str);
856 name_str = null;
857 attribute = null;
858 }
859 attributes = null;
860 }
861 }
862 // Otherwise we actually disable the name combobox
863 else {
864 name.setEnabled(false);
865 }
866 // Now name_to_values should contain a list of unique attribute names each mapping to a list of attribute values.
867 for(Iterator name_iterator = name_to_values.keySet().iterator(); name_iterator.hasNext(); ) {
868 name.add(name_iterator.next());
869 }
870 // Now pritty up the dialog depending on the action type
871 if(source == add_attribute) {
872 add_type = true;
873 Dictionary.setText(this, "MEM.AddAttribute");
874 if(current_collection_file != null) {
875 // Name is empty in this one, however values must be the current elements in the collection.
876 java.util.List values = Gatherer.c_man.msm.getElements();
877 for(int i = 0; i < values.size(); i++) {
878 value.add(new NameElementWrapperEntry(values.get(i)));
879 }
880 values = null;
881 }
882 setVisible(true);
883 }
884 else if(current_attribute != -1) {
885 AttributeTableModel model = null;
886 switch(current_attribute_type) {
887 case MEMNode.COLLECTION:
888 model = (AttributeTableModel) profile_attributes.getModel();
889 break;
890 case MEMNode.ELEMENT:
891 model = (AttributeTableModel) element_attributes.getModel();
892 break;
893 case MEMNode.SET:
894 model = (AttributeTableModel) set_attributes.getModel();
895 break;
896 }
897 add_type = false;
898 Dictionary.setText(this, "MEM.EditAttribute");
899 String name_str = (String) model.getValueAt(current_attribute, 0);
900 String value_str = (String) model.getValueAt(current_attribute, model.getColumnCount() - 1);
901 model = null;
902 // Retrieve the appropriate value model
903 java.util.List values = (java.util.List) name_to_values.get(name_str);
904 // Only possible for collection file selections.
905 if(values == null) {
906 values = Gatherer.c_man.msm.getElements();
907 }
908 name.setSelectedItem(name_str);
909 name_str = null;
910 for(int i = 0; i < values.size(); i++) {
911 Object temp_value = values.get(i);
912 if(temp_value instanceof ElementWrapper) {
913 value.add(new NameElementWrapperEntry(temp_value));
914 }
915 else {
916 value.add(temp_value);
917 }
918 }
919 values = null;
920 value.setSelectedItem(value_str);
921 value_str = null;
922 setVisible(true);
923 }
924 }
925 source = null;
926 }
927
928
929 private boolean addOrEditCollectionAttribute(AttributeTableModel model)
930 {
931 String name_str = name.getSelectedItem().toString();
932 String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM);
933
934 // Remove the existing attribute if this is an edit
935 if(!add_type && current_attribute != -1) {
936 String old_source = (String) model.getValueAt(current_attribute, 0);
937 Gatherer.c_man.msm.profiler.removeAction(current_collection_file, old_source);
938 old_source = null;
939 model.removeRow(current_attribute);
940 }
941
942 boolean cont = true;
943 // Check that there isn't already an entry for this attribute
944 if (!model.contains(name_str, 0)) {
945 // Add profile
946 Gatherer.c_man.msm.profiler.addAction(current_collection_file, name_str, value_str);
947 // Update attribute table
948 model.add(new Attribute(name_str, value_str));
949 }
950 // Otherwise show an error message and do not proceed
951 else {
952 cont = false;
953 JOptionPane.showMessageDialog(self, Dictionary.get("MEM.Attribute_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
954 }
955
956 value_str = null;
957 name_str = null;
958 return cont;
959 }
960
961
962 private boolean addOrEditSetAttribute(AttributeTableModel model)
963 {
964 String name_str = name.getSelectedItem().toString();
965 String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM);
966
967 // Remove the existing attribute if this is an edit
968 if(!add_type && current_attribute != -1) {
969 current_set.removeAttribute(name_str);
970 // Update attribute table
971 model.removeRow(current_attribute);
972 }
973
974 boolean cont = true;
975 // Check that there isn't already an entry for this attribute
976 if (!model.contains(name_str, 0)) {
977 // Add the new attribute
978 current_set.addAttribute(name_str, value_str);
979 // Update the attribute table
980 model.add(new Attribute(name_str, value_str));
981 }
982 // Otherwise show an error message and do not proceed
983 else {
984 cont = false;
985 JOptionPane.showMessageDialog(self, Dictionary.get("MEM.Attribute_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
986 }
987
988 value_str = null;
989 name_str = null;
990 return cont;
991 }
992
993
994 private boolean addOrEditElementAttribute(AttributeTableModel model)
995 {
996 // 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.
997 String name_str = name.getSelectedItem().toString();
998 String language_code = (String) language_box.getSelectedItem();
999 String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM);
1000
1001 // Remove the existing attribute if this is an edit
1002 if(!add_type && current_attribute != -1) {
1003 Attribute old_attribute = model.getAttribute(current_attribute);
1004 String old_value_str = old_attribute.value;
1005 String old_lang_code = old_attribute.language;
1006 current_element.removeAttribute(name_str, old_lang_code, old_value_str);
1007 // Update the attribute table
1008 model.removeRow(current_attribute);
1009 }
1010
1011 // Add the new attribute
1012 current_element.addAttribute(name_str, language_code, value_str);
1013 // Update the attribute table
1014 int row = model.add(new Attribute(name_str, language_code, value_str));
1015 element_attributes.setRowSelectionInterval(row, row);
1016
1017 value_str = null;
1018 language_code = null;
1019 name_str = null;
1020 return true;
1021 }
1022
1023
1024 public void dispose() {
1025 cancel_button = null;
1026 name = null;
1027 name_to_values = null;
1028 ok_button = null;
1029 target = null;
1030 value = null;
1031 ///ystem.err.println("Dispose AddOrEditAttributeActionListener");
1032 super.dispose();
1033 }
1034 }
1035
1036 private class AddElementActionListener
1037 extends ModalDialog
1038 implements ActionListener {
1039 private JButton cancel_button = null;
1040 private JButton ok_button = null;
1041 private JLabel set_field = null;
1042 private NonWhitespaceField name_field = null;
1043 public AddElementActionListener() {
1044 super(self);
1045 setModal(true);
1046 setSize(ADD_ELEMENT_SIZE);
1047 // Creation
1048 JPanel content_pane = (JPanel) getContentPane();
1049 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
1050 JPanel center_pane = new JPanel();
1051 center_pane.setOpaque(false);
1052
1053 JPanel set_pane = new JPanel();
1054 set_pane.setOpaque(false);
1055 JLabel set_label = new JLabel();
1056 set_label.setOpaque(false);
1057 Dictionary.setText(set_label, "MEM.Set");
1058 set_field = new JLabel();
1059 set_field.setOpaque(false);
1060
1061 JPanel name_pane = new JPanel();
1062 name_pane.setOpaque(false);
1063 JLabel name_label = new JLabel();
1064 name_label.setOpaque(false);
1065 Dictionary.setText(name_label, "MEM.Name");
1066 name_field = new NonWhitespaceField();
1067 name_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1068 name_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1069 name_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1070 name_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1071 Dictionary.setTooltip(name_field, "MEM.Element_Name_Tooltip");
1072
1073 JPanel button_pane = new JPanel();
1074 button_pane.setOpaque(false);
1075
1076 ok_button = new GLIButton();
1077 ok_button.setMnemonic(KeyEvent.VK_O);
1078 Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip");
1079 cancel_button = new GLIButton();
1080 cancel_button.setMnemonic(KeyEvent.VK_C);
1081 Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip");
1082
1083 TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
1084
1085 // Connection
1086 cancel_button.addActionListener(this);
1087 ok_button.addActionListener(this);
1088 ok_button_enabler.add(name_field);
1089
1090 // Layout
1091 set_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
1092 set_pane.setLayout(new BorderLayout());
1093 set_pane.add(set_label, BorderLayout.WEST);
1094 set_pane.add(set_field, BorderLayout.CENTER);
1095
1096 name_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
1097 name_pane.setLayout(new BorderLayout(5,0));
1098 name_pane.add(name_label, BorderLayout.WEST);
1099 name_pane.add(name_field, BorderLayout.CENTER);
1100
1101 center_pane.setLayout(new GridLayout(2,1,0,0));
1102 center_pane.add(set_pane);
1103 center_pane.add(name_pane);
1104
1105 button_pane.setLayout(new GridLayout(1,2,0,5));
1106 button_pane.add(ok_button);
1107 button_pane.add(cancel_button);
1108
1109 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
1110 content_pane.setLayout(new BorderLayout());
1111 content_pane.add(center_pane, BorderLayout.CENTER);
1112 content_pane.add(button_pane, BorderLayout.SOUTH);
1113
1114 setLocation((Gatherer.config.screen_size.width - ADD_ELEMENT_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_ELEMENT_SIZE.height) / 2);
1115 }
1116
1117 /** 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
1118 * @param event An <strong>ActionEvent</strong> containing information about the event.
1119 */
1120 public void actionPerformed(ActionEvent event) {
1121 Object source = event.getSource();
1122 if(source == ok_button) {
1123 // Add then dispose
1124 String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM);
1125 // If this element doesn't already exist.
1126 if(!current_set.containsElement(name_str)) {
1127 // Add it,
1128 String language_code = Gatherer.config.getLanguage();
1129 ElementWrapper element = current_set.addElement(name_str, language_code);
1130 // Then update the tree
1131 model.add(current_node, element, MEMNode.ELEMENT);
1132 // Signal that the metadata set has changed
1133 Gatherer.c_man.msm.fireSetChanged(current_set);
1134
1135 // Done
1136 element = null;
1137 setVisible(false);
1138 }
1139 // Otherwise show an error message and do not proceed.
1140 else {
1141 JOptionPane.showMessageDialog(self, Dictionary.get("MEM.Element_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1142 }
1143 name_str = null;
1144 }
1145 else if(source == cancel_button) {
1146 // Dispose
1147 setVisible(false);
1148 }
1149 else {
1150 if(current_set != null) {
1151 // You can't manually add elements to the Greenstone metadata set.
1152 if(!current_set.getNamespace().equals("")) {
1153 set_field.setText(current_set.toString());
1154 name_field.setText("");
1155 // Display
1156 setVisible(true);
1157 }
1158 // Warn the user that they can't do that dave.
1159 else {
1160 JOptionPane.showMessageDialog(self, Dictionary.get("MEM.Cannot_Add_Elements_To_Greenstone_MDS"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1161 }
1162 }
1163 }
1164 source = null;
1165 }
1166
1167 public void dispose() {
1168 cancel_button = null;
1169 ok_button = null;
1170 name_field = null;
1171 set_field = null;
1172 ///ystem.err.println("Dispose AddElementActionListener");
1173 super.dispose();
1174 }
1175 }
1176
1177 private class AddFileActionListener
1178 extends ModalDialog
1179 implements ActionListener {
1180 private JButton cancel_button = null;
1181 private JButton ok_button = null;
1182 private JTextField name_field = null;
1183 public AddFileActionListener() {
1184 super(self);
1185 setModal(true);
1186 setSize(ADD_FILE_SIZE);
1187 // Creation
1188 JPanel content_pane = (JPanel) getContentPane();
1189 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
1190 JPanel center_pane = new JPanel();
1191 center_pane.setOpaque(false);
1192 JPanel profile_pane = new JPanel();
1193 profile_pane.setOpaque(false);
1194 JLabel profile_label = new JLabel();
1195 profile_label.setOpaque(false);
1196 Dictionary.setText(profile_label, "MEM.Profile");
1197
1198 JPanel name_pane = new JPanel();
1199 name_pane.setOpaque(false);
1200 JLabel name_label = new JLabel();
1201 name_label.setOpaque(false);
1202 Dictionary.setText(name_label, "MEM.Name");
1203 name_field = new JTextField();
1204 name_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1205 name_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1206 name_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1207 name_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1208 Dictionary.setTooltip(name_field, "MEM.Profile_Name_Tooltip");
1209
1210 JPanel button_pane = new JPanel();
1211 button_pane.setOpaque(false);
1212
1213 ok_button = new GLIButton();
1214 ok_button.setMnemonic(KeyEvent.VK_O);
1215 Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip");
1216 cancel_button = new GLIButton();
1217 cancel_button.setMnemonic(KeyEvent.VK_C);
1218 Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip");
1219
1220 TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
1221
1222 // Connection
1223 cancel_button.addActionListener(this);
1224 ok_button.addActionListener(this);
1225 ok_button_enabler.add(name_field);
1226
1227 // Layout
1228 profile_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
1229 profile_pane.setLayout(new BorderLayout());
1230 profile_pane.add(profile_label, BorderLayout.CENTER);
1231
1232 name_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,5));
1233 name_pane.setLayout(new BorderLayout(5,0));
1234 name_pane.add(name_label, BorderLayout.WEST);
1235 name_pane.add(name_field, BorderLayout.CENTER);
1236
1237 center_pane.setLayout(new GridLayout(2,1,0,0));
1238 center_pane.add(profile_pane);
1239 center_pane.add(name_pane);
1240
1241 button_pane.setLayout(new GridLayout(1,2,0,5));
1242 button_pane.add(ok_button);
1243 button_pane.add(cancel_button);
1244
1245 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
1246 content_pane.setLayout(new BorderLayout());
1247 content_pane.add(center_pane, BorderLayout.CENTER);
1248 content_pane.add(button_pane, BorderLayout.SOUTH);
1249
1250 setLocation((Gatherer.config.screen_size.width - ADD_FILE_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_FILE_SIZE.height) / 2);
1251 }
1252 /** 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
1253 * @param event An <strong>ActionEvent</strong> containing information about the event.
1254 */
1255 public void actionPerformed(ActionEvent event) {
1256 Object source = event.getSource();
1257 if(source == ok_button) {
1258 String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM);
1259 // Ensure that this source doesn't already exist.
1260 if(!Gatherer.c_man.msm.profiler.containsSource(name_str)) {
1261 // Add source with empty hashmap of actions.
1262 Gatherer.c_man.msm.profiler.addSource(name_str);
1263 // Add to tree
1264 model.add(model.getProfileNode(), name_str, MEMNode.COLLECTION);
1265 setVisible(false);
1266 }
1267 // Otherwise warn the user and don't hide the prompt.
1268 else {
1269 JOptionPane.showMessageDialog(self, Dictionary.get("MEM.File_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1270 }
1271 name_str = null;
1272 }
1273 else if(source == cancel_button) {
1274 setVisible(false);
1275 }
1276 else {
1277 name_field.setText("");
1278 setVisible(true);
1279 }
1280 source = null;
1281 }
1282
1283 public void dispose() {
1284 cancel_button = null;
1285 ok_button = null;
1286 name_field = null;
1287 ///ystem.err.println("Dispose AddFileActionListener");
1288 super.dispose();
1289 }
1290 }
1291
1292 private class AddSetActionListener
1293 extends ModalDialog
1294 implements ActionListener {
1295 private JButton cancel_button = null;
1296 private JButton ok_button = null;
1297 private JTextField name_field = null;
1298 private JTextField namespace_field = null;
1299 public AddSetActionListener() {
1300 super(self);
1301 setModal(true);
1302 setSize(ADD_SET_SIZE);
1303 Dictionary.setText(this, "MEM.AddSet");
1304
1305 // Creation
1306 JPanel content_pane = (JPanel) getContentPane();
1307 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
1308 JPanel center_pane = new JPanel();
1309 center_pane.setOpaque(false);
1310
1311 JPanel label_pane = new JPanel();
1312 JPanel boxes_pane = new JPanel();
1313
1314 JLabel namespace_label = new JLabel();
1315 namespace_label.setOpaque(false);
1316 Dictionary.setText(namespace_label, "MEM.Namespace");
1317 namespace_field = TransformCharacterTextField.createNamespaceTextField();
1318 namespace_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1319 namespace_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1320 namespace_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1321 namespace_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1322 Dictionary.setTooltip(namespace_field, "MEM.Set_Namespace_Tooltip");
1323
1324 JLabel name_label = new JLabel();
1325 name_label.setOpaque(false);
1326 Dictionary.setText(name_label, "MEM.Name");
1327 name_field = new JTextField();
1328 name_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1329 name_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1330 name_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1331 name_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1332 Dictionary.setTooltip(name_field, "MEM.Set_Name_Tooltip");
1333
1334 JPanel button_pane = new JPanel();
1335 button_pane.setOpaque(false);
1336
1337 ok_button = new GLIButton();
1338 ok_button.setMnemonic(KeyEvent.VK_O);
1339 Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip");
1340 cancel_button = new GLIButton();
1341 cancel_button.setMnemonic(KeyEvent.VK_C);
1342 Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip");
1343 TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
1344
1345 // Connection
1346 cancel_button.addActionListener(this);
1347 ok_button.addActionListener(this);
1348 ok_button_enabler.add(name_field);
1349 ok_button_enabler.add(namespace_field);
1350
1351 // Layout
1352 label_pane.setLayout(new GridLayout(2,1,0,5));
1353 label_pane.add(name_label);
1354 label_pane.add(namespace_label);
1355
1356 boxes_pane.setLayout(new GridLayout(2,1,0,5));
1357 boxes_pane.add(name_field);
1358 boxes_pane.add(namespace_field);
1359
1360 center_pane.setLayout(new BorderLayout(5,0));
1361 center_pane.add(label_pane, BorderLayout.WEST);
1362 center_pane.add(boxes_pane, BorderLayout.CENTER);
1363
1364 button_pane.setLayout(new GridLayout(1,2,0,5));
1365 button_pane.add(ok_button);
1366 button_pane.add(cancel_button);
1367
1368 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
1369 content_pane.setLayout(new BorderLayout());
1370 content_pane.add(center_pane, BorderLayout.CENTER);
1371 content_pane.add(button_pane, BorderLayout.SOUTH);
1372
1373 setLocation((Gatherer.config.screen_size.width - ADD_SET_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_SET_SIZE.height) / 2);
1374 }
1375 /** 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
1376 * @param event An <strong>ActionEvent</strong> containing information about the event.
1377 */
1378 public void actionPerformed(ActionEvent event) {
1379 Object source = event.getSource();
1380 if(source == ok_button) {
1381 String namespace_str = namespace_field.getText();
1382 String name_str = Codec.transform(Codec.transformUnicode(name_field.getText()), Codec.TEXT_TO_DOM);
1383 // Ensure the set doesn't already exist
1384 if(Gatherer.c_man.msm.getSet(name_str) == null) {
1385 MetadataSet set = Gatherer.c_man.msm.addSet(namespace_str, name_str);
1386 // Update tree.
1387 model.add(null, set, MEMNode.SET);
1388 // Done
1389 set = null;
1390 setVisible(false);
1391 }
1392 // Otherwise show a warning.
1393 else {
1394 JOptionPane.showMessageDialog(self, Dictionary.get("MEM.Set_Already_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1395 }
1396 name_str = null;
1397 namespace_str = null;
1398 }
1399 else if(source == cancel_button) {
1400 setVisible(false);
1401 }
1402 else {
1403 name_field.setText("");
1404 setVisible(true);
1405 }
1406 }
1407
1408 public void dispose() {
1409 cancel_button = null;
1410 ok_button = null;
1411 name_field = null;
1412 ///ystem.err.println("Dispose AddSetActionListener");
1413 super.dispose();
1414 }
1415 }
1416
1417 private class AddOrEditValueActionListener
1418 extends ModalDialog
1419 implements ActionListener, TreeSelectionListener {
1420 private boolean add_type = true;
1421 private boolean ignore = false;
1422 private GValueNode subject_node = null;
1423 private JButton cancel_button = null;
1424 private JButton ok_button = null;
1425 private JTextArea value = null;
1426 private SmarterTree subject_tree = null;
1427
1428 /** Constructor. */
1429 public AddOrEditValueActionListener() {
1430 super(self);
1431 this.setModal(true);
1432 this.setSize(ADD_OR_EDIT_VALUE_SIZE);
1433
1434 // Create
1435 JPanel content_pane = (JPanel) getContentPane();
1436 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
1437 JPanel center_pane = new JPanel();
1438 center_pane.setOpaque(false);
1439 JPanel inner_pane = new JPanel();
1440 inner_pane.setOpaque(false);
1441 JPanel subject_tree_pane = new JPanel();
1442 subject_tree_pane.setOpaque(false);
1443 JLabel subject_tree_label = new JLabel();
1444 subject_tree_label.setOpaque(false);
1445 Dictionary.setText(subject_tree_label, "MEM.Subject");
1446 subject_tree = new SmarterTree();
1447 subject_tree.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1448 subject_tree.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1449 subject_tree.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1450 subject_tree.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1451 JPanel value_pane = new JPanel();
1452 value_pane.setOpaque(false);
1453 JLabel value_label = new JLabel();
1454 value_label.setOpaque(false);
1455 Dictionary.setText(value_label, "MEM.Value");
1456 value = new JTextArea();
1457 value.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1458 value.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1459 value.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1460 value.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1461 Dictionary.setTooltip(value, "MEM.Value_Tooltip");
1462
1463 JPanel button_pane = new JPanel();
1464 button_pane.setOpaque(false);
1465
1466 ok_button = new GLIButton();
1467 ok_button.setMnemonic(KeyEvent.VK_O);
1468 ok_button.setEnabled(false);
1469 Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip");
1470 cancel_button = new GLIButton();
1471 cancel_button.setMnemonic(KeyEvent.VK_C);
1472 Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip");
1473 TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
1474
1475 // Connect
1476 ok_button_enabler.add(value);
1477 cancel_button.addActionListener(this);
1478 ok_button.addActionListener(this);
1479 subject_tree.addTreeSelectionListener(this);
1480
1481 // Layout
1482 subject_tree_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
1483 subject_tree_pane.setLayout(new BorderLayout());
1484 subject_tree_pane.add(subject_tree_label, BorderLayout.NORTH);
1485 subject_tree_pane.add(new JScrollPane(subject_tree), BorderLayout.CENTER);
1486
1487 value_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
1488 value_pane.setLayout(new BorderLayout());
1489 value_pane.add(value_label, BorderLayout.NORTH);
1490 value_pane.add(new JScrollPane(value), BorderLayout.CENTER);
1491
1492 inner_pane.setLayout(new GridLayout(2,1));
1493 inner_pane.add(subject_tree_pane);
1494 inner_pane.add(value_pane);
1495
1496 button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
1497 button_pane.setLayout(new GridLayout(1,2,5,5));
1498 button_pane.add(ok_button);
1499 button_pane.add(cancel_button);
1500
1501 content_pane.setLayout(new BorderLayout());
1502 content_pane.add(inner_pane, BorderLayout.CENTER);
1503 content_pane.add(button_pane, BorderLayout.SOUTH);
1504 setLocation((Gatherer.config.screen_size.width - ADD_OR_EDIT_VALUE_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_OR_EDIT_VALUE_SIZE.height) / 2);
1505 }
1506 /** 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.
1507 * @param event An <strong>ActionEvent</strong> containing information about the event.
1508 */
1509 public void actionPerformed(ActionEvent event) {
1510 Object source = event.getSource();
1511 if(source == ok_button) {
1512 String value_str = Codec.transform(Codec.transformUnicode(value.getText()), Codec.TEXT_TO_DOM);
1513 // Now we action as necessary
1514 GValueModel model = Gatherer.c_man.msm.getValueTree(current_element);
1515 if(add_type) {
1516 ///ystem.err.println("Add type - insert node: " + value.getText() + " into " + subject_node);
1517 // Add this value to the tree.
1518 model.addValue(value_str, subject_node);
1519 }
1520 else {
1521 // Rewrite this value in the DOM model. Note that this will automatically rewrite all assignments as they are live references.
1522 current_value_node.setValue(value_str);
1523 // Now insert the node into the currently selected subject, but only if the parent has changed.
1524 if(subject_node != current_value_node.getParent()) {
1525 GValueNode old_subject_node = (GValueNode) current_value_node.getParent();
1526 // Find the new values position in subject_nodes children.
1527 GValueNode sibling = null;
1528 int index = 0;
1529 boolean found = false;
1530 while(index < subject_node.getChildCount() && !found) {
1531 sibling = (GValueNode) subject_node.getChildAt(index);
1532 int order = current_value_node.toString().compareToIgnoreCase(sibling.toString());
1533 // If the sibling is 'greater than' or comes after current value then insert.
1534 if(order < 0) {
1535 // Insert. This will coincidently remove from original parent.
1536 Node parent_node = subject_node.getElement();
1537 Node child_node = current_value_node.getElement();
1538 Node sibling_node = sibling.getElement();
1539 parent_node.insertBefore(child_node, sibling_node);
1540 found = true;
1541 }
1542 // The value already exists exactly as is. In theory this case can never happenm but just incase do nothing more.
1543 else if(order == 0) {
1544 found = true;
1545 }
1546 // The sibling is 'less than' or before the current value, keep looking.
1547 else {
1548 index++;
1549 }
1550 }
1551 // If we haven't done so yet, insert the current node. This will coincidently remove from original parent.
1552 if(!found) {
1553 Node parent_node = subject_node.getElement();
1554 Node child_node = current_value_node.getElement();
1555 parent_node.appendChild(child_node);
1556 }
1557 // Inform the tree model what two nodes structures have changed (origin and destination).
1558 //subject_node.unmap();
1559 //old_subject_node.unmap();
1560 model.nodeStructureChanged(old_subject_node);
1561 model.nodeStructureChanged(subject_node);
1562 }
1563 // And if a data change was made tell the tree its data model is ka-bluey.
1564 else {
1565 model.nodeChanged(current_value_node);
1566 }
1567 }
1568 model = null;
1569 // Hide dialog
1570 setVisible(false);
1571
1572 }
1573 else if(source == cancel_button) {
1574 // Hide dialog
1575 setVisible(false);
1576
1577 }
1578 else {
1579 // Reset dialog
1580 // current_value_node
1581 GValueModel model = Gatherer.c_man.msm.getValueTree(current_element);
1582 subject_tree.setModel(model);
1583 // Task specific
1584 if(source == add_value) {
1585 add_type = true;
1586 if(current_value_node != null) {
1587 subject_node = current_value_node;
1588 }
1589 else {
1590 subject_node = (GValueNode) model.getRoot();
1591 }
1592 value.setText("");
1593 Dictionary.setText(this, "MEM.AddValue");
1594 }
1595 else {
1596 add_type = false;
1597 if(current_value_node != null) {
1598 subject_node = (GValueNode) current_value_node.getParent();
1599 }
1600 else {
1601 subject_node = (GValueNode) model.getRoot();
1602 }
1603 value.setText(Codec.transform(current_value_node.toString(), Codec.DOM_TO_TEXT));
1604 Dictionary.setText(this, "MEM.EditValue");
1605 }
1606 model = null;
1607 if(subject_node != null) {
1608 TreePath path = new TreePath(subject_node.getPath());
1609 subject_tree.scrollPathToVisible(path);
1610 subject_tree.setSelectionPath(path);
1611 path = null;
1612 }
1613 // Display
1614 setVisible(true);
1615 }
1616 }
1617
1618 public void dispose() {
1619 cancel_button = null;
1620 ok_button = null;
1621 subject_node = null;
1622 subject_tree = null;
1623 value = null;
1624 ///ystem.err.println("Dispose AddOrEditValueActionListener");
1625 super.dispose();
1626 }
1627
1628 public void valueChanged(TreeSelectionEvent event) {
1629 if(subject_tree.getSelectionCount() > 0 && !ignore) {
1630 ignore = true;
1631 TreePath selected_path = subject_tree.getSelectionPath();
1632 GValueNode requested_node = (GValueNode) selected_path.getLastPathComponent();
1633 // Ensure the requested node is not a descendant of the current_value_node
1634 if(current_value_node != null) {
1635 if(!add_type && current_value_node.isNodeDescendant(requested_node)) {
1636 TreePath path = new TreePath(subject_node.getPath());
1637 subject_tree.scrollPathToVisible(path);
1638 subject_tree.setSelectionPath(path);
1639 }
1640 else {
1641 subject_node = requested_node;
1642 }
1643 }
1644 selected_path = null;
1645 ignore = false;
1646 }
1647 }
1648 }
1649
1650 private class CloseActionListener
1651 extends ModalDialog
1652 implements ActionListener {
1653 /** 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.
1654 * @param event An <strong>ActionEvent</strong> containing information about the event.
1655 */
1656 public void actionPerformed(ActionEvent event) {
1657 // I don't know why this is causing a problem even after the dialog has been disposed, but it is.
1658 GValueModel value_model = Gatherer.c_man.msm.getValueTree(current_element);
1659 if (value_model != null) {
1660 value_model.removeTreeModelListener(keep_root_expanded_listener);
1661 }
1662 self.dispose();
1663 }
1664 }
1665
1666 /** This listener is responsible for keeping the root node of a value tree expanded where and when possible. */
1667 private class KeepTreeRootExpandedListener
1668 implements TreeModelListener {
1669 /** Invoked after a node (or a set of siblings) has changed in some way. */
1670 public void treeNodesChanged(TreeModelEvent e) {
1671 }
1672 /** Invoked after nodes have been inserted into the tree. */
1673 public void treeNodesInserted(TreeModelEvent e) {
1674 if(element_values != null && element_values.getModel() != null && element_values.getModel().getRoot() != null) {
1675 element_values.expandPath(new TreePath(element_values.getModel().getRoot()));
1676 }
1677 }
1678 /** Invoked after nodes have been removed from the tree. */
1679 public void treeNodesRemoved(TreeModelEvent e) {
1680 }
1681 /** Invoked after the tree has drastically changed structure from a given node down. */
1682 public void treeStructureChanged(TreeModelEvent e) {
1683 element_values.expandPath(new TreePath(element_values.getModel().getRoot()));
1684 }
1685 }
1686
1687 private class RemoveAttributeActionListener
1688 implements ActionListener {
1689 /** 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
1690 * @param event An <strong>ActionEvent</strong> containing information about the event.
1691 */
1692 public void actionPerformed(ActionEvent event) {
1693 if(current_attribute != -1) {
1694 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]);
1695 // Remove this attribute
1696 if(result == 0) {
1697 ignore = true;
1698 // Attributes are tricky little beasties, as they can come from several different places and depend upon what other little beasties have been selected
1699 // Has a collection file been selected...
1700 if(current_collection_file != null) {
1701 // Remove a profile
1702 String source = (String) profile_attributes.getValueAt(current_attribute, 0);
1703 Gatherer.c_man.msm.profiler.removeAction(current_collection_file, source);
1704 source = null;
1705 // Refresh table
1706 ((AttributeTableModel)profile_attributes.getModel()).removeRow(current_attribute);
1707 }
1708 // or has an element been selected
1709 else if(current_element != null) {
1710 // Remove element attribute
1711 String name = (String) element_attributes.getValueAt(current_attribute, 0);
1712 String language = (String) element_attributes.getValueAt(current_attribute, 1);
1713 String value = (String) element_attributes.getValueAt(current_attribute, 2);
1714 current_element.removeAttribute(name, language, value);
1715
1716 // Refresh table
1717 ((AttributeTableModel)element_attributes.getModel()).removeRow(current_attribute);
1718 }
1719 else if(current_set != null) {
1720 String name = (String) set_attributes.getValueAt(current_attribute, 0);
1721 // Remove set attribute
1722 current_set.removeAttribute(name);
1723 // Refresh table
1724 ((AttributeTableModel)set_attributes.getModel()).removeRow(current_attribute);
1725 }
1726 // Disable buttons
1727 edit_attribute.setEnabled(false);
1728 remove_attribute.setEnabled(false);
1729 ignore = false;
1730 }
1731 }
1732 }
1733 }
1734
1735 private class RemoveElementActionListener
1736 implements ActionListener {
1737 /** 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.
1738 * @param event An <strong>ActionEvent</strong> containing information about the event.
1739 */
1740 public void actionPerformed(ActionEvent event) {
1741 if(current_element != null) {
1742 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]);
1743 // Remove this attribute
1744 if(result == 0) {
1745 ignore = true;
1746 Gatherer.c_man.msm.removeElement(current_element);
1747 // Clear selection
1748 mds_tree.clearSelection();
1749 model.remove(current_element.toString(), MEMNode.ELEMENT);
1750 // Meanwhile disable/enable controls given we had an element selected, but no longer do.
1751 remove_element.setEnabled(false);
1752 // Show a blank panel.
1753 card_layout.show(details_pane, BLANK);
1754 ignore = false;
1755 }
1756 }
1757 else {
1758 ///ystem.err.println("No current element selected.");
1759 }
1760 }
1761 }
1762
1763 private class RemoveFileActionListener
1764 implements ActionListener {
1765 /** 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.
1766 * @param event An <strong>ActionEvent</strong> containing information about the event.
1767 */
1768 public void actionPerformed(ActionEvent event) {
1769 if(current_collection_file != null) {
1770 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]);
1771 // Remove the current collection file profile from the profiler.
1772 if(result == 0) {
1773 ignore = true;
1774 Gatherer.c_man.msm.profiler.removeProfile(current_collection_file);
1775 // Clear selection
1776 mds_tree.clearSelection();
1777 model.remove(current_collection_file, MEMNode.COLLECTION);
1778 // Meanwhile disable/enable controls given we had a set selected, but no longer do.
1779 remove_file.setEnabled(false);
1780 // Show a blank panel.
1781 card_layout.show(details_pane, BLANK);
1782 ignore = false;
1783 }
1784 }
1785 }
1786 }
1787
1788 private class RemoveSetActionListener
1789 implements ActionListener {
1790 /** 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
1791 * @param event An <strong>ActionEvent</strong> containing information about the event.
1792 */
1793 public void actionPerformed(ActionEvent event) {
1794 if(current_set != null) {
1795 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]);
1796 // Remove the currently selected set
1797 if(result == 0) {
1798 ignore = true;
1799 Gatherer.c_man.msm.removeSet(current_set);
1800 // Clear selection
1801 mds_tree.clearSelection();
1802 model.remove(current_set.toString(), MEMNode.SET);
1803 // Meanwhile disable/enable controls given we had a set selected, but no longer do.
1804 remove_set.setEnabled(false);
1805 // Show a blank panel.
1806 card_layout.show(details_pane, BLANK);
1807 ignore = false;
1808 }
1809 }
1810 }
1811 }
1812 /** 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. */
1813 private class RemoveValueActionListener
1814 implements ActionListener {
1815 /** 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
1816 * @param event An <strong>ActionEvent</strong> containing information about the event.
1817 */
1818 public void actionPerformed(ActionEvent event) {
1819 if(current_value_node != null) {
1820 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]);
1821 // Remove the current selected value
1822 if(result == 0) {
1823 ignore = true;
1824 GValueModel model = (GValueModel) element_values.getModel();
1825 model.removeValue(current_value_node);
1826 // Meanwhile disable/enable controls given we had a value selected, but no longer do.
1827 edit_value.setEnabled(false);
1828 remove_value.setEnabled(false);
1829 ignore = false;
1830 }
1831 }
1832 }
1833 }
1834
1835 /** Used to enable a certain target component if and only if all the registered text fields contain non-zero length strings. */
1836 private class TextFieldEnabler
1837 implements DocumentListener {
1838 private boolean ignore = false;
1839 private Component target = null;
1840 private JTextComponent[] fields = null;
1841 public TextFieldEnabler(Component target) {
1842 super();
1843 this.target = target;
1844 }
1845 public void add(JTextComponent field) {
1846 // Record this field as being one we depend upon
1847 if(fields == null) {
1848 fields = new JTextComponent[1];
1849 fields[0] = field;
1850 }
1851 else {
1852 JTextComponent[] temp = new JTextComponent[fields.length + 1];
1853 System.arraycopy(fields, 0, temp, 0, fields.length);
1854 temp[fields.length] = field;
1855 fields = temp;
1856 temp = null;
1857 }
1858 // Add the appropriate listener
1859 field.getDocument().addDocumentListener(this);
1860 }
1861 /** Gives notification that an attribute or set of attributes changed. */
1862 public void changedUpdate(DocumentEvent e) {
1863 canEnable();
1864 }
1865 /** Gives notification that there was an insert into the document. */
1866 public void insertUpdate(DocumentEvent e) {
1867 canEnable();
1868 }
1869 /** Gives notification that a portion of the document has been removed. */
1870 public void removeUpdate(DocumentEvent e) {
1871 canEnable();
1872 }
1873 private void canEnable() {
1874 if(!ignore) {
1875 ignore = true;
1876 boolean can_enable = true;
1877 for(int i = 0; can_enable && i < fields.length; i++) {
1878 can_enable = can_enable && (fields[i].getText().length() > 0);
1879 }
1880 target.setEnabled(can_enable);
1881 ignore = false;
1882 }
1883 }
1884 }
1885
1886 private class AttributesListSelectionListener
1887 implements ListSelectionListener {
1888 private JTable table = null;
1889 public AttributesListSelectionListener(JTable table) {
1890 this.table = table;
1891 }
1892 public void valueChanged(ListSelectionEvent event) {
1893 if(!event.getValueIsAdjusting()) {
1894 if((current_attribute = table.getSelectedRow()) != -1) {
1895 edit_attribute.setEnabled(true);
1896 remove_attribute.setEnabled(true);
1897 }
1898 else {
1899 current_attribute = -1;
1900 edit_attribute.setEnabled(false);
1901 remove_attribute.setEnabled(false);
1902 }
1903 }
1904 }
1905 }
1906
1907 private class ElementValuesTreeSelectionListener
1908 implements TreeSelectionListener {
1909 public void valueChanged(TreeSelectionEvent event) {
1910 if(element_values.getSelectionCount() > 0) {
1911 // Retrieve the selected value node.
1912 TreePath selected_path = element_values.getSelectionPath();
1913 current_value_node = (GValueNode) selected_path.getLastPathComponent();
1914 edit_value.setEnabled(true);
1915 remove_value.setEnabled(true);
1916 }
1917 else {
1918 current_value_node = null;
1919 edit_value.setEnabled(false);
1920 remove_value.setEnabled(false);
1921 }
1922 }
1923 }
1924
1925 private class MDSTreeSelectionListener
1926 implements TreeSelectionListener {
1927 public void valueChanged(TreeSelectionEvent event) {
1928 if(!ignore) {
1929 // Clear all variables based on previous tree selection
1930 current_collection_file = null;
1931 current_element = null;
1932 current_set = null;
1933 // Now process the node selected
1934 TreePath path = event.getPath();
1935 current_node = (MEMNode)path.getLastPathComponent();
1936 // What we show depends on the node type...
1937 AttributeTableModel atm = null;
1938 TreeSet attributes = null;
1939 current_attribute_type = current_node.getType();
1940 switch(current_attribute_type) {
1941 case MEMNode.COLLECTION:
1942 current_collection_file = (String) current_node.getUserObject();
1943 atm = current_node.getModel();
1944 if(atm == null) {
1945 ArrayList sources = Gatherer.c_man.msm.profiler.getSources(current_collection_file);
1946 attributes = new TreeSet();
1947 for(int i = 0; i < sources.size(); i++) {
1948 String source = (String) sources.get(i);
1949 String action = Gatherer.c_man.msm.profiler.getAction(current_collection_file, source);
1950 if (action == null) {
1951 action = Dictionary.get("MEM.Ignore");
1952 }
1953 attributes.add(new Attribute(source, action));
1954 }
1955 atm = new AttributeTableModel(attributes, Dictionary.get("MEM.Source"), Dictionary.get("MEM.Target"), Dictionary.get("MEM.Ignore"));
1956 //current_node.setModel(atm);
1957 }
1958 profile_attributes.setModel(atm);
1959 atm.setScrollPane(profile_attributes_scroll);
1960 atm.setTable(profile_attributes);
1961
1962 card_layout.show(details_pane, PROFILE);
1963 setControls(true, false, false, true, false, false, true, false, false, false, false, false);
1964 break;
1965 case MEMNode.ELEMENT:
1966 current_element = current_node.getElement();
1967 atm = current_node.getModel();
1968 if(atm == null) {
1969 atm = new AttributeTableModel(current_element.getAttributes(), Dictionary.get("MEM.Name"), Dictionary.get("MEM.Language_Code"), Dictionary.get("MEM.Value"), "");
1970 //current_node.setModel(atm);
1971 }
1972 element_attributes.setModel(atm);
1973 atm.setScrollPane(element_attributes_scroll);
1974 atm.setTable(element_attributes);
1975
1976 // Be careful not to add the keep_root_expanded_listener over and over!
1977 GValueModel value_model = Gatherer.c_man.msm.getValueTree(current_element);
1978 if(value_model != null) {
1979 value_model.removeTreeModelListener(keep_root_expanded_listener); // Remove it if its already there
1980 value_model.addTreeModelListener(keep_root_expanded_listener); // Then add again.
1981 element_values.setModel(value_model);
1982 element_values_layout.show(element_values_pane, VALUES);
1983 // Meanwhile disable/enable controls depending on this Element selection.
1984 setControls(true, false, false, false, false, true, true, false, false, true, false, false);
1985 }
1986 else {
1987 element_values_layout.show(element_values_pane, BLANK);
1988 // Meanwhile disable/enable controls depending on this Element selection.
1989 setControls(true, false, false, false, false, false, true, false, false, false, false, false);
1990 }
1991 card_layout.show(details_pane, ELEMENT);
1992 break;
1993 case MEMNode.SET:
1994 current_set = current_node.getSet();
1995 atm = current_node.getModel();
1996 if(atm == null) {
1997 NamedNodeMap temp = current_set.getAttributes();
1998 attributes = new TreeSet();
1999 for(int i = 0; i < temp.getLength(); i++) {
2000 Attr attribute = (Attr) temp.item(i);
2001 // 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.
2002 if(!attribute.getName().equals("namespace")) {
2003 attributes.add(new Attribute(attribute.getName(), attribute.getValue()));
2004 }
2005 attribute = null;
2006 }
2007 atm = new AttributeTableModel(attributes, Dictionary.get("MEM.Name"), Dictionary.get("MEM.Value"), "");
2008 //current_node.setModel(atm);
2009 temp = null;
2010 }
2011 set_attributes.setModel(atm);
2012 atm.setScrollPane(set_attributes_scroll);
2013 atm.setTable(set_attributes);
2014
2015 card_layout.show(details_pane, SET);
2016 attributes = null;
2017 // Meanwhile disable/enable controls depending on this Element selection.
2018 setControls(true, true, false, false, true, false, true, false, false, false, false, false);
2019 break;
2020 case MEMNode.PROFILER:
2021 // Meanwhile disable/enable controls depending on this Element selection.
2022 setControls(true, false, true, false, false, false, false, false, false, false, false, false);
2023 default:
2024 // Show a blank panel.
2025 card_layout.show(details_pane, BLANK);
2026 }
2027 attributes = null;
2028 path = null;
2029 atm = null;
2030 }
2031 }
2032 }
2033
2034 private class MEMTreeCellRenderer
2035 extends DefaultTreeCellRenderer {
2036 public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
2037 super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
2038 setToolTipText(value.toString());
2039 return this;
2040 }
2041 }
2042
2043 /** Wrap a ElementWrapper so we get its name when we ask for toString(), not its identifier. */
2044 private class NameElementWrapperEntry
2045 implements Comparable {
2046 private ElementWrapper element_wrapper = null;
2047 public NameElementWrapperEntry(Object object) {
2048 this.element_wrapper = (ElementWrapper) object;
2049 }
2050 public int compareTo(Object object) {
2051 return element_wrapper.compareTo(object);
2052 }
2053 public boolean equals(Object object) {
2054 return element_wrapper.equals(object);
2055 }
2056 public String toString() {
2057 return element_wrapper.getName();
2058 }
2059 }
2060}
Note: See TracBrowser for help on using the repository browser.