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

Last change on this file since 5349 was 5349, checked in by mdewsnip, 21 years ago

Changed dictionary get()s to have the whole key.

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