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

Last change on this file since 4436 was 4436, checked in by jmt12, 21 years ago

2030094 & 2030095: Fixed two places where NPEs were being thrown, mostly because of accessing non-existing columns of a table, or indeed the wrong table.

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