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

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

Can now add/edit/remove element attributes properly.

  • Property svn:keywords set to Author Date Id Revision
File size: 78.6 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 success = true;
638 AttributeTableModel model;
639
640 // Add or edit a collect/set/element attribute
641 switch(current_attribute_type) {
642 case MEMNode.COLLECTION:
643 model = (AttributeTableModel) profile_attributes.getModel();
644 success = addOrEditCollectionAttribute(model);
645 break;
646 case MEMNode.SET:
647 model = (AttributeTableModel) set_attributes.getModel();
648 success = addOrEditSetAttribute(model);
649 break;
650 case MEMNode.ELEMENT:
651 model = (AttributeTableModel) element_attributes.getModel();
652 success = addOrEditElementAttribute(model);
653 break;
654 }
655
656 if (success) {
657 // Hide dialog
658 setVisible(false);
659 }
660 }
661 else if(source == cancel_button) {
662 // Hide dialog
663 setVisible(false);
664 }
665 else if(source == name) {
666 Object object = name.getSelectedItem();
667 if(object != null) {
668 java.util.List values = (java.util.List) name_to_values.get(object.toString());
669 if(values == null) { // Only for collection files, otherwise values != null && values.size() == 0
670 values = Gatherer.c_man.msm.getElements();
671 }
672 value.clear();
673 for(int i = 0; i < values.size(); i++) {
674 value.add(values.get(i));
675 }
676 }
677 }
678 else {
679 name_to_values.clear();
680 name.clear();
681 value.clear();
682 value.setText("");
683 // Build the correct name_to_values mapping
684 // Attributes are slightly tricky as they can come from several sources. Has a collection file been selected...
685 if(current_collection_file != null) {
686 target.setText(current_collection_file);
687 // Name is empty in this one, however values must be the current elements in the collection.
688 language_box.setEnabled(false);
689 }
690 // or has an element been selected
691 else if(current_element != null) {
692 target.setText(current_element.toString());
693 // Develop a model for name based on known attributes from all other elements.
694 java.util.List elements = Gatherer.c_man.msm.getElements();
695 for(int i = 0; i < elements.size(); i++) {
696 ElementWrapper element = (ElementWrapper) elements.get(i);
697 TreeSet attributes = element.getAttributes();
698 for(Iterator attribute_iterator = attributes.iterator(); attribute_iterator.hasNext(); ) {
699 Attribute attribute = (Attribute) attribute_iterator.next();
700 java.util.List values = (java.util.List) name_to_values.get(attribute.name);
701 if(values == null) {
702 values = new ArrayList();
703 name_to_values.put(attribute.name, values);
704 }
705 if(!values.contains(attribute.value)) {
706 values.add(attribute.value);
707 }
708 values = null;
709 attribute = null;
710 }
711 attributes = null;
712 element = null;
713 }
714 elements = null;
715 language_box.setEnabled(true);
716 }
717 else if(current_set != null) {
718 target.setText(current_set.toString());
719 // 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.
720 java.util.List sets = Gatherer.c_man.msm.getSets();
721 for(int i = 0; i < sets.size(); i++) {
722 MetadataSet set = (MetadataSet) sets.get(i);
723 NamedNodeMap attributes = set.getAttributes();
724 for(int j = 0; j < attributes.getLength(); j++) {
725 Attr attribute = (Attr) attributes.item(j);
726 String name_str = attribute.getName();
727 String value_str = attribute.getValue();
728 java.util.List values = (java.util.List) name_to_values.get(name_str);
729 if(values == null) {
730 values = new ArrayList();
731 name_to_values.put(name_str, values);
732 }
733 if(!values.contains(value_str)) {
734 values.add(value_str);
735 }
736 values = null;
737 value_str = null;
738 name_str = null;
739 attribute = null;
740 }
741 attributes = null;
742 set = null;
743 language_box.setEnabled(false);
744 }
745 sets = null;
746 // If this is an add remove all the attributes already present in the current set.
747 if(source == add_attribute) {
748 name.setEnabled(true);
749 NamedNodeMap attributes = current_set.getAttributes();
750 for(int i = 0; i < attributes.getLength(); i++) {
751 Attr attribute = (Attr) attributes.item(i);
752 String name_str = attribute.getName();
753 name_to_values.remove(name_str);
754 name_str = null;
755 attribute = null;
756 }
757 attributes = null;
758 }
759 }
760 // Otherwise we actually disable the name combobox
761 else {
762 name.setEnabled(false);
763 }
764 // Now name_to_values should contain a list of unique attribute names each mapping to a list of attribute values.
765 for(Iterator name_iterator = name_to_values.keySet().iterator(); name_iterator.hasNext(); ) {
766 name.add(name_iterator.next());
767 }
768 // Now pritty up the dialog depending on the action type
769 if(source == add_attribute) {
770 add_type = true;
771 setTitle(get("AddAttribute"));
772 if(current_collection_file != null) {
773 // Name is empty in this one, however values must be the current elements in the collection.
774 java.util.List values = Gatherer.c_man.msm.getElements();
775 for(int i = 0; i < values.size(); i++) {
776 value.add(new NameElementWrapperEntry(values.get(i)));
777 }
778 values = null;
779 }
780 setVisible(true);
781 }
782 else if(current_attribute != -1) {
783 AttributeTableModel model = null;
784 switch(current_attribute_type) {
785 case MEMNode.COLLECTION:
786 model = (AttributeTableModel) profile_attributes.getModel();
787 break;
788 case MEMNode.ELEMENT:
789 model = (AttributeTableModel) element_attributes.getModel();
790 break;
791 case MEMNode.SET:
792 model = (AttributeTableModel) set_attributes.getModel();
793 break;
794 }
795 add_type = false;
796 setTitle(get("EditAttribute"));
797 String name_str = (String) model.getValueAt(current_attribute, 0);
798 String value_str = (String) model.getValueAt(current_attribute, model.getColumnCount() - 1);
799 model = null;
800 // Retrieve the appropriate value model
801 java.util.List values = (java.util.List) name_to_values.get(name_str);
802 // Only possible for collection file selections.
803 if(values == null) {
804 values = Gatherer.c_man.msm.getElements();
805 }
806 name.setSelectedItem(name_str);
807 name_str = null;
808 for(int i = 0; i < values.size(); i++) {
809 Object temp_value = values.get(i);
810 if(temp_value instanceof ElementWrapper) {
811 value.add(new NameElementWrapperEntry(temp_value));
812 }
813 else {
814 value.add(temp_value);
815 }
816 }
817 values = null;
818 value.setSelectedItem(value_str);
819 value_str = null;
820 setVisible(true);
821 }
822 }
823 source = null;
824 }
825
826
827 private boolean addOrEditCollectionAttribute(AttributeTableModel model)
828 {
829 String name_str = name.getSelectedItem().toString();
830 String value_str = value.getText();
831
832 // Remove the existing attribute if this is an edit
833 if(!add_type && current_attribute != -1) {
834 String old_source = (String) model.getValueAt(current_attribute, 0);
835 Gatherer.c_man.msm.profiler.removeAction(current_collection_file, old_source);
836 old_source = null;
837 model.removeRow(current_attribute);
838 }
839
840 boolean cont = true;
841 // Check that there isn't already an entry for this attribute
842 if (!model.contains(name_str, 0)) {
843 // Add profile
844 Gatherer.c_man.msm.profiler.addAction(current_collection_file, name_str, value_str);
845 // Update attribute table
846 model.add(new Attribute(name_str, value_str));
847 }
848 // Otherwise show an error message and do not proceed
849 else {
850 cont = false;
851 JOptionPane.showMessageDialog(self, get("Attribute_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
852 }
853
854 value_str = null;
855 name_str = null;
856 return cont;
857 }
858
859
860 private boolean addOrEditSetAttribute(AttributeTableModel model)
861 {
862 String name_str = name.getSelectedItem().toString();
863 String value_str = value.getText();
864
865 // Remove the existing attribute if this is an edit
866 if(!add_type && current_attribute != -1) {
867 current_set.removeAttribute(name_str);
868 // Update attribute table
869 model.removeRow(current_attribute);
870 }
871
872 boolean cont = true;
873 // Check that there isn't already an entry for this attribute
874 if (!model.contains(name_str, 0)) {
875 // Add the new attribute
876 current_set.addAttribute(name_str, value_str);
877 // Update the attribute table
878 model.add(new Attribute(name_str, value_str));
879 }
880 // Otherwise show an error message and do not proceed
881 else {
882 cont = false;
883 JOptionPane.showMessageDialog(self, get("Attribute_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
884 }
885
886 value_str = null;
887 name_str = null;
888 return cont;
889 }
890
891
892 private boolean addOrEditElementAttribute(AttributeTableModel model)
893 {
894 // 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.
895 String name_str = name.getSelectedItem().toString();
896 String language_code = ((Language)language_box.getSelectedItem()).getCode();
897 String value_str = value.getText();
898
899 // Remove the existing attribute if this is an edit
900 if(!add_type && current_attribute != -1) {
901 String current_value_str = model.getAttribute(current_attribute).value;
902 current_element.removeAttribute(name_str, language_code, current_value_str);
903 // Update the attribute table
904 model.removeRow(current_attribute);
905 }
906
907 // Add the new attribute
908 current_element.addAttribute(name_str, language_code, value_str);
909 // Update the attribute table
910 model.add(new Attribute(name_str, language_code, value_str));
911
912 value_str = null;
913 language_code = null;
914 name_str = null;
915 return true;
916 }
917
918
919 public void dispose() {
920 cancel_button = null;
921 name = null;
922 name_to_values = null;
923 ok_button = null;
924 target = null;
925 value = null;
926 }
927 }
928
929 private class AddElementActionListener
930 extends ModalDialog
931 implements ActionListener {
932 private JButton cancel_button = null;
933 private JButton ok_button = null;
934 private JLabel set_field = null;
935 private JTextField name_field = null;
936 public AddElementActionListener() {
937 super(self);
938 setModal(true);
939 setSize(ADD_ELEMENT_SIZE);
940 // Creation
941 JPanel content_pane = (JPanel) getContentPane();
942 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
943 JPanel center_pane = new JPanel();
944 center_pane.setOpaque(false);
945 JPanel set_pane = new JPanel();
946 set_pane.setOpaque(false);
947 JLabel set_label = new JLabel(get("Set"));
948 set_label.setOpaque(false);
949 set_label.setPreferredSize(LABEL_SIZE);
950 set_field = new JLabel();
951 set_field.setOpaque(false);
952 JPanel name_pane = new JPanel();
953 name_pane.setOpaque(false);
954 JLabel name_label = new JLabel(get("Name"));
955 name_label.setOpaque(false);
956 name_label.setPreferredSize(LABEL_SIZE);
957 name_field = new JTextField();
958 name_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
959 name_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
960 name_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
961 name_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
962 JPanel button_pane = new JPanel();
963 button_pane.setOpaque(false);
964 ok_button = new JButton(get("General.OK"));
965 cancel_button = new JButton(get("General.Cancel"));
966 TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
967 // Connection
968 cancel_button.addActionListener(this);
969 ok_button.addActionListener(this);
970 ok_button_enabler.add(name_field);
971 // Layout
972 set_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
973 set_pane.setLayout(new BorderLayout());
974 set_pane.add(set_label, BorderLayout.WEST);
975 set_pane.add(set_field, BorderLayout.CENTER);
976
977 name_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
978 name_pane.setLayout(new BorderLayout());
979 name_pane.add(name_label, BorderLayout.WEST);
980 name_pane.add(name_field, BorderLayout.CENTER);
981
982 center_pane.setLayout(new GridLayout(2,1,0,0));
983 center_pane.add(set_pane);
984 center_pane.add(name_pane);
985
986 button_pane.setLayout(new GridLayout(1,2,0,5));
987 button_pane.add(ok_button);
988 button_pane.add(cancel_button);
989
990 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
991 content_pane.setLayout(new BorderLayout());
992 content_pane.add(center_pane, BorderLayout.CENTER);
993 content_pane.add(button_pane, BorderLayout.SOUTH);
994
995 setLocation((Gatherer.config.screen_size.width - ADD_ELEMENT_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_ELEMENT_SIZE.height) / 2);
996 }
997 /** 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
998 * @param event An <strong>ActionEvent</strong> containing information about the event.
999 */
1000 public void actionPerformed(ActionEvent event) {
1001 Object source = event.getSource();
1002 if(source == ok_button) {
1003 // Add then dispose
1004 String name_str = name_field.getText();
1005 // If this element doesn't already exist.
1006 if(!current_set.containsElement(name_str)) {
1007 // Add it,
1008 ElementWrapper element = current_set.addElement(name_str);
1009 // Then update the tree
1010 model.add(current_node, element, MEMNode.ELEMENT);
1011 // Done
1012 element = null;
1013 setVisible(false);
1014 }
1015 // Otherwise show an error message and do not proceed.
1016 else {
1017 JOptionPane.showMessageDialog(self, get("Element_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
1018 }
1019 name_str = null;
1020 }
1021 else if(source == cancel_button) {
1022 // Dispose
1023 setVisible(false);
1024
1025 }
1026 else {
1027 if(current_set != null) {
1028 // You can't manually add elements to the Greenstone metadata set.
1029 if(!current_set.getNamespace().equals("")) {
1030 set_field.setText(current_set.toString());
1031 name_field.setText("");
1032 // Display
1033 setVisible(true);
1034 }
1035 // Warn the user that they can't do that dave.
1036 else {
1037 JOptionPane.showMessageDialog(self, get("Cannot_Add_Elements_To_Greenstone_MDS"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
1038 }
1039 }
1040 }
1041 source = null;
1042 }
1043
1044 public void dispose() {
1045 cancel_button = null;
1046 ok_button = null;
1047 name_field = null;
1048 set_field = null;
1049 }
1050 }
1051
1052 private class AddFileActionListener
1053 extends ModalDialog
1054 implements ActionListener {
1055 private JButton cancel_button = null;
1056 private JButton ok_button = null;
1057 private JTextField name_field = null;
1058 public AddFileActionListener() {
1059 super(self);
1060 setModal(true);
1061 setSize(ADD_FILE_SIZE);
1062 // Creation
1063 JPanel content_pane = (JPanel) getContentPane();
1064 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
1065 JPanel center_pane = new JPanel();
1066 center_pane.setOpaque(false);
1067 JPanel profile_pane = new JPanel();
1068 profile_pane.setOpaque(false);
1069 JLabel profile_label = new JLabel(get("Profile"));
1070 profile_label.setOpaque(false);
1071 profile_label.setPreferredSize(LABEL_SIZE);
1072 JPanel name_pane = new JPanel();
1073 name_pane.setOpaque(false);
1074 JLabel name_label = new JLabel(get("Name"));
1075 name_label.setOpaque(false);
1076 name_label.setPreferredSize(LABEL_SIZE);
1077 name_field = new JTextField();
1078 name_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1079 name_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1080 name_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1081 name_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1082 JPanel button_pane = new JPanel();
1083 button_pane.setOpaque(false);
1084 ok_button = new JButton(get("General.OK"));
1085 cancel_button = new JButton(get("General.Cancel"));
1086 TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
1087 // Connection
1088 cancel_button.addActionListener(this);
1089 ok_button.addActionListener(this);
1090 ok_button_enabler.add(name_field);
1091 // Layout
1092 profile_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
1093 profile_pane.setLayout(new BorderLayout());
1094 profile_pane.add(profile_label, BorderLayout.CENTER);
1095
1096 name_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
1097 name_pane.setLayout(new BorderLayout());
1098 name_pane.add(name_label, BorderLayout.WEST);
1099 name_pane.add(name_field, BorderLayout.CENTER);
1100
1101 center_pane.setLayout(new GridLayout(2,1,0,0));
1102 center_pane.add(profile_pane);
1103 center_pane.add(name_pane);
1104
1105 button_pane.setLayout(new GridLayout(1,2,0,5));
1106 button_pane.add(ok_button);
1107 button_pane.add(cancel_button);
1108
1109 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
1110 content_pane.setLayout(new BorderLayout());
1111 content_pane.add(center_pane, BorderLayout.CENTER);
1112 content_pane.add(button_pane, BorderLayout.SOUTH);
1113
1114 setLocation((Gatherer.config.screen_size.width - ADD_FILE_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_FILE_SIZE.height) / 2);
1115 }
1116 /** 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
1117 * @param event An <strong>ActionEvent</strong> containing information about the event.
1118 */
1119 public void actionPerformed(ActionEvent event) {
1120 Object source = event.getSource();
1121 if(source == ok_button) {
1122 String name_str = name_field.getText();
1123 // Ensure that this source doesn't already exist.
1124 if(!Gatherer.c_man.msm.profiler.containsSource(name_str)) {
1125 // Add source with empty hashmap of actions.
1126 Gatherer.c_man.msm.profiler.addSource(name_str);
1127 // Add to tree
1128 model.add(model.getProfileNode(), name_str, MEMNode.COLLECTION);
1129 setVisible(false);
1130 }
1131 // Otherwise warn the user and don't hide the prompt.
1132 else {
1133 JOptionPane.showMessageDialog(self, get("File_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
1134 }
1135 name_str = null;
1136 }
1137 else if(source == cancel_button) {
1138 setVisible(false);
1139
1140 }
1141 else {
1142 name_field.setText("");
1143 setVisible(true);
1144 }
1145 source = null;
1146 }
1147
1148 public void dispose() {
1149 cancel_button = null;
1150 ok_button = null;
1151 name_field = null;
1152 }
1153 }
1154
1155 private class AddSetActionListener
1156 extends ModalDialog
1157 implements ActionListener {
1158 private JButton cancel_button = null;
1159 private JButton ok_button = null;
1160 private JTextField name_field = null;
1161 private JTextField namespace_field = null;
1162 public AddSetActionListener() {
1163 super(self);
1164 setModal(true);
1165 setSize(ADD_SET_SIZE);
1166 setTitle(get("AddSet"));
1167 // Creation
1168 JPanel content_pane = (JPanel) getContentPane();
1169 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
1170 JPanel center_pane = new JPanel();
1171 center_pane.setOpaque(false);
1172
1173 JPanel namespace_pane = new JPanel();
1174 namespace_pane.setOpaque(false);
1175 JLabel namespace_label = new JLabel(get("Namespace"));
1176 namespace_label.setOpaque(false);
1177 namespace_label.setPreferredSize(LABEL_SIZE);
1178 namespace_field = new JTextField();
1179 namespace_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1180 namespace_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1181 namespace_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1182 namespace_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1183
1184 JPanel name_pane = new JPanel();
1185 name_pane.setOpaque(false);
1186 JLabel name_label = new JLabel(get("Name"));
1187 name_label.setOpaque(false);
1188 name_label.setPreferredSize(LABEL_SIZE);
1189 name_field = new JTextField();
1190 name_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1191 name_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1192 name_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1193 name_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1194
1195 JPanel button_pane = new JPanel();
1196 button_pane.setOpaque(false);
1197 ok_button = new JButton(get("General.OK"));
1198 ok_button.setEnabled(false);
1199 cancel_button = new JButton(get("General.Cancel"));
1200 TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
1201 // Connection
1202 cancel_button.addActionListener(this);
1203 ok_button.addActionListener(this);
1204 ok_button_enabler.add(name_field);
1205 ok_button_enabler.add(namespace_field);
1206 // Layout
1207 namespace_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
1208 namespace_pane.setLayout(new BorderLayout());
1209 namespace_pane.add(namespace_label, BorderLayout.WEST);
1210 namespace_pane.add(namespace_field, BorderLayout.CENTER);
1211
1212 name_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
1213 name_pane.setLayout(new BorderLayout());
1214 name_pane.add(name_label, BorderLayout.WEST);
1215 name_pane.add(name_field, BorderLayout.CENTER);
1216
1217 center_pane.setLayout(new GridLayout(2,1));
1218 center_pane.add(namespace_pane);
1219 center_pane.add(name_pane);
1220
1221 button_pane.setLayout(new GridLayout(1,2,0,5));
1222 button_pane.add(ok_button);
1223 button_pane.add(cancel_button);
1224
1225 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
1226 content_pane.setLayout(new BorderLayout());
1227 content_pane.add(center_pane, BorderLayout.CENTER);
1228 content_pane.add(button_pane, BorderLayout.SOUTH);
1229
1230 setLocation((Gatherer.config.screen_size.width - ADD_SET_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_SET_SIZE.height) / 2);
1231 }
1232 /** 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
1233 * @param event An <strong>ActionEvent</strong> containing information about the event.
1234 */
1235 public void actionPerformed(ActionEvent event) {
1236 Object source = event.getSource();
1237 if(source == ok_button) {
1238 String namespace_str = namespace_field.getText();
1239 String name_str = name_field.getText();
1240 // Ensure the set doesn't already exist
1241 if(Gatherer.c_man.msm.getSet(name_str) == null) {
1242 MetadataSet set = Gatherer.c_man.msm.addSet(namespace_str, name_str);
1243 // Update tree.
1244 model.add(null, set, MEMNode.SET);
1245 // Done
1246 set = null;
1247 setVisible(false);
1248 }
1249 // Otherwise show a warning.
1250 else {
1251 JOptionPane.showMessageDialog(self, get("Set_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
1252 }
1253 name_str = null;
1254 namespace_str = null;
1255 }
1256 else if(source == cancel_button) {
1257 setVisible(false);
1258 }
1259 else {
1260 name_field.setText("");
1261 setVisible(true);
1262 }
1263 }
1264
1265 public void dispose() {
1266 cancel_button = null;
1267 ok_button = null;
1268 name_field = null;
1269 }
1270 }
1271
1272 private class AddOrEditValueActionListener
1273 extends ModalDialog
1274 implements ActionListener, TreeSelectionListener {
1275 private boolean add_type = true;
1276 private boolean ignore = false;
1277 private GValueNode subject_node = null;
1278 private JButton cancel_button = null;
1279 private JButton ok_button = null;
1280 private JTextArea value = null;
1281 private JTextField alias = null;
1282 private SmarterTree subject_tree = null;
1283
1284 /** Constructor. */
1285 public AddOrEditValueActionListener() {
1286 super(self);
1287 this.setModal(true);
1288 this.setSize(ADD_OR_EDIT_VALUE_SIZE);
1289 // Create
1290 JPanel content_pane = (JPanel) getContentPane();
1291 content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
1292 JPanel center_pane = new JPanel();
1293 center_pane.setOpaque(false);
1294 JPanel inner_pane = new JPanel();
1295 inner_pane.setOpaque(false);
1296 JPanel subject_tree_pane = new JPanel();
1297 subject_tree_pane.setOpaque(false);
1298 JLabel subject_tree_label = new JLabel(get("Subject"));
1299 subject_tree_label.setOpaque(false);
1300 subject_tree = new SmarterTree();
1301 subject_tree.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1302 subject_tree.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1303 subject_tree.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1304 subject_tree.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1305 JPanel value_pane = new JPanel();
1306 value_pane.setOpaque(false);
1307 JLabel value_label = new JLabel(get("Value"));
1308 value_label.setOpaque(false);
1309 value = new JTextArea();
1310 value.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1311 value.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1312 value.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1313 value.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1314 JPanel alias_pane = new JPanel();
1315 alias_pane.setOpaque(false);
1316 JLabel alias_label = new JLabel(get("Alias"));
1317 alias_label.setOpaque(false);
1318 alias_label.setPreferredSize(LABEL_SIZE);
1319 alias = new JTextField();
1320 alias.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
1321 alias.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
1322 alias.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
1323 alias.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
1324 JPanel button_pane = new JPanel();
1325 button_pane.setOpaque(false);
1326 ok_button = new JButton(get("General.OK"));
1327 ok_button.setEnabled(false);
1328 TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
1329 cancel_button = new JButton(get("General.Cancel"));
1330 // Connect
1331 ok_button_enabler.add(value);
1332 cancel_button.addActionListener(this);
1333 ok_button.addActionListener(this);
1334 subject_tree.addTreeSelectionListener(this);
1335 // Layout
1336 subject_tree_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
1337 subject_tree_pane.setLayout(new BorderLayout());
1338 subject_tree_pane.add(subject_tree_label, BorderLayout.NORTH);
1339 subject_tree_pane.add(new JScrollPane(subject_tree), BorderLayout.CENTER);
1340
1341 value_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
1342 value_pane.setLayout(new BorderLayout());
1343 value_pane.add(value_label, BorderLayout.NORTH);
1344 value_pane.add(new JScrollPane(value), BorderLayout.CENTER);
1345
1346 inner_pane.setLayout(new GridLayout(2,1));
1347 inner_pane.add(subject_tree_pane);
1348 inner_pane.add(value_pane);
1349
1350 alias_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
1351 alias_pane.setLayout(new BorderLayout());
1352 alias_pane.add(alias_label, BorderLayout.WEST);
1353 alias_pane.add(alias, BorderLayout.CENTER);
1354
1355 center_pane.setLayout(new BorderLayout());
1356 center_pane.add(inner_pane, BorderLayout.CENTER);
1357 center_pane.add(alias_pane, BorderLayout.SOUTH);
1358
1359 button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
1360 button_pane.setLayout(new GridLayout(1,2,5,5));
1361 button_pane.add(ok_button);
1362 button_pane.add(cancel_button);
1363
1364 content_pane.setLayout(new BorderLayout());
1365 content_pane.add(center_pane, BorderLayout.CENTER);
1366 content_pane.add(button_pane, BorderLayout.SOUTH);
1367 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);
1368 }
1369 /** 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.
1370 * @param event An <strong>ActionEvent</strong> containing information about the event.
1371 */
1372 public void actionPerformed(ActionEvent event) {
1373 Object source = event.getSource();
1374 if(source == ok_button) {
1375 // Now we action as necessary
1376 GValueModel model = Gatherer.c_man.msm.getValueTree(current_element);
1377 if(add_type) {
1378 ///ystem.err.println("Add type - insert node: " + value.getText() + " into " + subject_node);
1379 // Add this value to the tree.
1380 model.addValue(value.getText(), subject_node, alias.getText());
1381 }
1382 else {
1383 // Rewrite this value in the DOM model. Note that this will automatically rewrite all assignments as they are live references.
1384 current_value_node.setValue(value.getText());
1385 current_value_node.setAlias(alias.getText());
1386 // Now insert the node into the currently selected subject, but only if the parent has changed.
1387 if(subject_node != current_value_node.getParent()) {
1388 GValueNode old_subject_node = (GValueNode) current_value_node.getParent();
1389 // Find the new values position in subject_nodes children.
1390 GValueNode sibling = null;
1391 int index = 0;
1392 boolean found = false;
1393 while(index < subject_node.getChildCount() && !found) {
1394 sibling = (GValueNode) subject_node.getChildAt(index);
1395 int order = current_value_node.toString().compareToIgnoreCase(sibling.toString());
1396 // If the sibling is 'greater than' or comes after current value then insert.
1397 if(order < 0) {
1398 // Insert. This will coincidently remove from original parent.
1399 Node parent_node = subject_node.getElement();
1400 Node child_node = current_value_node.getElement();
1401 Node sibling_node = sibling.getElement();
1402 parent_node.insertBefore(child_node, sibling_node);
1403 found = true;
1404 }
1405 // The value already exists exactly as is. In theory this case can never happenm but just incase do nothing more.
1406 else if(order == 0) {
1407 found = true;
1408 }
1409 // The sibling is 'less than' or before the current value, keep looking.
1410 else {
1411 index++;
1412 }
1413 }
1414 // If we haven't done so yet, insert the current node. This will coincidently remove from original parent.
1415 if(!found) {
1416 Node parent_node = subject_node.getElement();
1417 Node child_node = current_value_node.getElement();
1418 parent_node.appendChild(child_node);
1419 }
1420 // Inform the tree model what two nodes structures have changed (origin and destination).
1421 //subject_node.unmap();
1422 //old_subject_node.unmap();
1423 model.nodeStructureChanged(old_subject_node);
1424 model.nodeStructureChanged(subject_node);
1425 }
1426 // And if a data change was made tell the tree its data model is ka-bluey.
1427 else {
1428 model.nodeChanged(current_value_node);
1429 }
1430 }
1431 model = null;
1432 // Hide dialog
1433 setVisible(false);
1434
1435 }
1436 else if(source == cancel_button) {
1437 // Hide dialog
1438 setVisible(false);
1439
1440 }
1441 else {
1442 // Reset dialog
1443 // current_value_node
1444 GValueModel model = Gatherer.c_man.msm.getValueTree(current_element);
1445 subject_tree.setModel(model);
1446 // Task specific
1447 if(source == add_value) {
1448 add_type = true;
1449 if(current_value_node != null) {
1450 subject_node = current_value_node;
1451 }
1452 else {
1453 subject_node = (GValueNode) model.getRoot();
1454 }
1455 value.setText("");
1456 alias.setText("");
1457 setTitle(get("AddValue"));
1458 }
1459 else {
1460 add_type = false;
1461 if(current_value_node != null) {
1462 subject_node = (GValueNode) current_value_node.getParent();
1463 }
1464 else {
1465 subject_node = (GValueNode) model.getRoot();
1466 }
1467 value.setText(current_value_node.toString());
1468 alias.setText(current_value_node.getAlias());
1469 setTitle(get("EditValue"));
1470 }
1471 model = null;
1472 if(subject_node != null) {
1473 TreePath path = new TreePath(subject_node.getPath());
1474 subject_tree.scrollPathToVisible(path);
1475 subject_tree.setSelectionPath(path);
1476 path = null;
1477 }
1478 // Display
1479 setVisible(true);
1480 }
1481 }
1482
1483 public void dispose() {
1484 alias = null;
1485 cancel_button = null;
1486 ok_button = null;
1487 subject_node = null;
1488 subject_tree = null;
1489 value = null;
1490 }
1491
1492 public void valueChanged(TreeSelectionEvent event) {
1493 if(subject_tree.getSelectionCount() > 0 && !ignore) {
1494 ignore = true;
1495 TreePath selected_path = subject_tree.getSelectionPath();
1496 GValueNode requested_node = (GValueNode) selected_path.getLastPathComponent();
1497 // Ensure the requested node is not a descendant of the current_value_node
1498 if(current_value_node != null) {
1499 if(!add_type && current_value_node.isNodeDescendant(requested_node)) {
1500 TreePath path = new TreePath(subject_node.getPath());
1501 subject_tree.scrollPathToVisible(path);
1502 subject_tree.setSelectionPath(path);
1503 }
1504 else {
1505 subject_node = requested_node;
1506 }
1507 }
1508 selected_path = null;
1509 ignore = false;
1510 }
1511 }
1512 }
1513
1514 private class CloseActionListener
1515 extends ModalDialog
1516 implements ActionListener {
1517 /** 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.
1518 * @param event An <strong>ActionEvent</strong> containing information about the event.
1519 */
1520 public void actionPerformed(ActionEvent event) {
1521 self.dispose();
1522 }
1523 }
1524
1525 /** This listener is responsible for keeping the root node of a value tree expanded where and when possible. */
1526 private class KeepTreeRootExpandedListener
1527 implements TreeModelListener {
1528 /** Invoked after a node (or a set of siblings) has changed in some way. */
1529 public void treeNodesChanged(TreeModelEvent e) {
1530 }
1531 /** Invoked after nodes have been inserted into the tree. */
1532 public void treeNodesInserted(TreeModelEvent e) {
1533 element_values.expandPath(new TreePath(element_values.getModel().getRoot()));
1534 }
1535 /** Invoked after nodes have been removed from the tree. */
1536 public void treeNodesRemoved(TreeModelEvent e) {
1537 }
1538 /** Invoked after the tree has drastically changed structure from a given node down. */
1539 public void treeStructureChanged(TreeModelEvent e) {
1540 element_values.expandPath(new TreePath(element_values.getModel().getRoot()));
1541 }
1542 }
1543
1544 private class RemoveAttributeActionListener
1545 implements ActionListener {
1546 /** 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
1547 * @param event An <strong>ActionEvent</strong> containing information about the event.
1548 */
1549 public void actionPerformed(ActionEvent event) {
1550 if(current_attribute != -1) {
1551 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]);
1552 // Remove this attribute
1553 if(result == 0) {
1554 ignore = true;
1555 // Attributes are tricky little beasties, as they can come from several different places and depend upon what other little beasties have been selected
1556 // Has a collection file been selected...
1557 if(current_collection_file != null) {
1558 // Remove a profile
1559 String source = (String) profile_attributes.getValueAt(current_attribute, 0);
1560 Gatherer.c_man.msm.profiler.removeAction(current_collection_file, source);
1561 source = null;
1562 // Refresh table
1563 ((AttributeTableModel)profile_attributes.getModel()).removeRow(current_attribute);
1564 }
1565 // or has an element been selected
1566 else if(current_element != null) {
1567 // Remove element attribute
1568 String name = (String) element_attributes.getValueAt(current_attribute, 0);
1569 String language = (String) element_attributes.getValueAt(current_attribute, 1);
1570 String value = (String) element_attributes.getValueAt(current_attribute, 2);
1571 current_element.removeAttribute(name, language, value);
1572
1573 // Refresh table
1574 ((AttributeTableModel)element_attributes.getModel()).removeRow(current_attribute);
1575 }
1576 else if(current_set != null) {
1577 String name = (String) set_attributes.getValueAt(current_attribute, 0);
1578 // Remove set attribute
1579 current_set.removeAttribute(name);
1580 // Refresh table
1581 ((AttributeTableModel)set_attributes.getModel()).removeRow(current_attribute);
1582 }
1583 // Disable buttons
1584 edit_attribute.setEnabled(false);
1585 remove_attribute.setEnabled(false);
1586 ignore = false;
1587 }
1588 }
1589 }
1590 }
1591
1592 private class RemoveElementActionListener
1593 implements ActionListener {
1594 /** 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.
1595 * @param event An <strong>ActionEvent</strong> containing information about the event.
1596 */
1597 public void actionPerformed(ActionEvent event) {
1598 if(current_element != null) {
1599 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]);
1600 // Remove this attribute
1601 if(result == 0) {
1602 ignore = true;
1603 Gatherer.c_man.msm.removeElement(current_element);
1604 // Clear selection
1605 mds_tree.clearSelection();
1606 model.remove(current_element.toString(), MEMNode.ELEMENT);
1607 // Meanwhile disable/enable controls given we had an element selected, but no longer do.
1608 remove_element.setEnabled(false);
1609 // Show a blank panel.
1610 card_layout.show(details_pane, BLANK);
1611 ignore = false;
1612 }
1613 }
1614 else {
1615 ///ystem.err.println("No current element selected.");
1616 }
1617 }
1618 }
1619
1620 private class RemoveFileActionListener
1621 implements ActionListener {
1622 /** 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.
1623 * @param event An <strong>ActionEvent</strong> containing information about the event.
1624 */
1625 public void actionPerformed(ActionEvent event) {
1626 if(current_collection_file != null) {
1627 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]);
1628 // Remove the current collection file profile from the profiler.
1629 if(result == 0) {
1630 ignore = true;
1631 Gatherer.c_man.msm.profiler.removeProfile(current_collection_file);
1632 // Clear selection
1633 mds_tree.clearSelection();
1634 model.remove(current_collection_file, MEMNode.COLLECTION);
1635 // Meanwhile disable/enable controls given we had a set selected, but no longer do.
1636 remove_file.setEnabled(false);
1637 // Show a blank panel.
1638 card_layout.show(details_pane, BLANK);
1639 ignore = false;
1640 }
1641 }
1642 }
1643 }
1644
1645 private class RemoveSetActionListener
1646 implements ActionListener {
1647 /** 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
1648 * @param event An <strong>ActionEvent</strong> containing information about the event.
1649 */
1650 public void actionPerformed(ActionEvent event) {
1651 if(current_set != null) {
1652 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]);
1653 // Remove the currently selected set
1654 if(result == 0) {
1655 ignore = true;
1656 Gatherer.c_man.msm.removeSet(current_set);
1657 // Clear selection
1658 mds_tree.clearSelection();
1659 model.remove(current_set.toString(), MEMNode.SET);
1660 // Meanwhile disable/enable controls given we had a set selected, but no longer do.
1661 remove_set.setEnabled(false);
1662 // Show a blank panel.
1663 card_layout.show(details_pane, BLANK);
1664 ignore = false;
1665 }
1666 }
1667 }
1668 }
1669 /** 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. */
1670 private class RemoveValueActionListener
1671 implements ActionListener {
1672 /** 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
1673 * @param event An <strong>ActionEvent</strong> containing information about the event.
1674 */
1675 public void actionPerformed(ActionEvent event) {
1676 if(current_value_node != null) {
1677 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]);
1678 // Remove the current selected value
1679 if(result == 0) {
1680 ignore = true;
1681 GValueModel model = (GValueModel) element_values.getModel();
1682 model.removeValue(current_value_node);
1683 // Meanwhile disable/enable controls given we had a value selected, but no longer do.
1684 edit_value.setEnabled(false);
1685 remove_value.setEnabled(false);
1686 ignore = false;
1687 }
1688 }
1689 }
1690 }
1691
1692 /** Used to enable a certain target component if and only if all the registered text fields contain non-zero length strings. */
1693 private class TextFieldEnabler
1694 implements DocumentListener {
1695 private boolean ignore = false;
1696 private Component target = null;
1697 private JTextComponent[] fields = null;
1698 public TextFieldEnabler(Component target) {
1699 super();
1700 this.target = target;
1701 }
1702 public void add(JTextComponent field) {
1703 // Record this field as being one we depend upon
1704 if(fields == null) {
1705 fields = new JTextComponent[1];
1706 fields[0] = field;
1707 }
1708 else {
1709 JTextComponent[] temp = new JTextComponent[fields.length + 1];
1710 System.arraycopy(fields, 0, temp, 0, fields.length);
1711 temp[fields.length] = field;
1712 fields = temp;
1713 temp = null;
1714 }
1715 // Add the appropriate listener
1716 field.getDocument().addDocumentListener(this);
1717 }
1718 /** Gives notification that an attribute or set of attributes changed. */
1719 public void changedUpdate(DocumentEvent e) {
1720 canEnable();
1721 }
1722 /** Gives notification that there was an insert into the document. */
1723 public void insertUpdate(DocumentEvent e) {
1724 canEnable();
1725 }
1726 /** Gives notification that a portion of the document has been removed. */
1727 public void removeUpdate(DocumentEvent e) {
1728 canEnable();
1729 }
1730 private void canEnable() {
1731 if(!ignore) {
1732 ignore = true;
1733 boolean can_enable = true;
1734 for(int i = 0; can_enable && i < fields.length; i++) {
1735 can_enable = can_enable && (fields[i].getText().length() > 0);
1736 }
1737 target.setEnabled(can_enable);
1738 ignore = false;
1739 }
1740 }
1741 }
1742
1743 private class AttributesListSelectionListener
1744 implements ListSelectionListener {
1745 private JTable table = null;
1746 public AttributesListSelectionListener(JTable table) {
1747 this.table = table;
1748 }
1749 public void valueChanged(ListSelectionEvent event) {
1750 if(!event.getValueIsAdjusting()) {
1751 if((current_attribute = table.getSelectedRow()) != -1) {
1752 edit_attribute.setEnabled(true);
1753 remove_attribute.setEnabled(true);
1754 }
1755 else {
1756 current_attribute = -1;
1757 edit_attribute.setEnabled(false);
1758 remove_attribute.setEnabled(false);
1759 }
1760 }
1761 }
1762 }
1763
1764 private class ElementValuesTreeSelectionListener
1765 implements TreeSelectionListener {
1766 public void valueChanged(TreeSelectionEvent event) {
1767 if(element_values.getSelectionCount() > 0) {
1768 // Retrieve the selected value node.
1769 TreePath selected_path = element_values.getSelectionPath();
1770 current_value_node = (GValueNode) selected_path.getLastPathComponent();
1771 edit_value.setEnabled(true);
1772 remove_value.setEnabled(true);
1773 }
1774 else {
1775 current_value_node = null;
1776 edit_value.setEnabled(false);
1777 remove_value.setEnabled(false);
1778 }
1779 }
1780 }
1781
1782 private class MDSTreeSelectionListener
1783 implements TreeSelectionListener {
1784 public void valueChanged(TreeSelectionEvent event) {
1785 if(!ignore) {
1786 // Clear all variables based on previous tree selection
1787 current_collection_file = null;
1788 current_element = null;
1789 current_set = null;
1790 // Now process the node selected
1791 TreePath path = event.getPath();
1792 current_node = (MEMNode)path.getLastPathComponent();
1793 // What we show depends on the node type...
1794 AttributeTableModel atm = null;
1795 TreeSet attributes = null;
1796 current_attribute_type = current_node.getType();
1797 switch(current_attribute_type) {
1798 case MEMNode.COLLECTION:
1799 current_collection_file = current_node.toString();
1800 atm = current_node.getModel();
1801 if(atm == null) {
1802 ArrayList sources = Gatherer.c_man.msm.profiler.getSources(current_collection_file);
1803 attributes = new TreeSet();
1804 for(int i = 0; i < sources.size(); i++) {
1805 String source = (String) sources.get(i);
1806 String action = Gatherer.c_man.msm.profiler.getAction(current_collection_file, source);
1807 if(action == null) {
1808 action = get("Ignore");
1809 }
1810 attributes.add(new Attribute(source, action));
1811 }
1812 atm = new AttributeTableModel(attributes, get("Source"), get("Target"), get("Ignore"));
1813 //current_node.setModel(atm);
1814 }
1815 profile_attributes.setModel(atm);
1816 atm.setScrollPane(profile_attributes_scroll);
1817 atm.setTable(profile_attributes);
1818
1819 card_layout.show(details_pane, PROFILE);
1820 setControls(true, false, false, true, false, false, true, false, false, false, false, false);
1821 break;
1822 case MEMNode.ELEMENT:
1823 current_element = current_node.getElement();
1824 atm = current_node.getModel();
1825 if(atm == null) {
1826 atm = new AttributeTableModel(current_element.getAttributes(), get("Name"), get("Language_Code"), get("Value"), "");
1827 //current_node.setModel(atm);
1828 }
1829 element_attributes.setModel(atm);
1830 atm.setScrollPane(element_attributes_scroll);
1831 atm.setTable(element_attributes);
1832
1833 // Be careful not to add the keep_root_expanded_listener over and over!
1834 GValueModel value_model = Gatherer.c_man.msm.getValueTree(current_element);
1835 if(value_model != null) {
1836 value_model.removeTreeModelListener(keep_root_expanded_listener); // Remove it if its already there
1837 value_model.addTreeModelListener(keep_root_expanded_listener); // Then add again.
1838 element_values.setModel(value_model);
1839 element_values_layout.show(element_values_pane, VALUES);
1840 // Meanwhile disable/enable controls depending on this Element selection.
1841 setControls(true, false, false, false, false, true, true, false, false, true, false, false);
1842 }
1843 else {
1844 element_values_layout.show(element_values_pane, BLANK);
1845 // Meanwhile disable/enable controls depending on this Element selection.
1846 setControls(true, false, false, false, false, false, true, false, false, false, false, false);
1847 }
1848 card_layout.show(details_pane, ELEMENT);
1849 break;
1850 case MEMNode.SET:
1851 current_set = current_node.getSet();
1852 atm = current_node.getModel();
1853 if(atm == null) {
1854 NamedNodeMap temp = current_set.getAttributes();
1855 attributes = new TreeSet();
1856 for(int i = 0; i < temp.getLength(); i++) {
1857 Attr attribute = (Attr) temp.item(i);
1858 // 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.
1859 if(!attribute.getName().equals("namespace")) {
1860 attributes.add(new Attribute(attribute.getName(), attribute.getValue()));
1861 }
1862 attribute = null;
1863 }
1864 atm = new AttributeTableModel(attributes, get("Name"), get("Value"), "");
1865 //current_node.setModel(atm);
1866 temp = null;
1867 }
1868 set_attributes.setModel(atm);
1869 atm.setScrollPane(set_attributes_scroll);
1870 atm.setTable(set_attributes);
1871
1872 card_layout.show(details_pane, SET);
1873 attributes = null;
1874 // Meanwhile disable/enable controls depending on this Element selection.
1875 setControls(true, true, false, false, true, false, true, false, false, false, false, false);
1876 break;
1877 case MEMNode.PROFILER:
1878 // Meanwhile disable/enable controls depending on this Element selection.
1879 setControls(true, false, true, false, false, false, false, false, false, false, false, false);
1880 default:
1881 // Show a blank panel.
1882 card_layout.show(details_pane, BLANK);
1883 }
1884 attributes = null;
1885 path = null;
1886 atm = null;
1887 }
1888 }
1889 }
1890
1891 private class MEMTreeCellRenderer
1892 extends DefaultTreeCellRenderer {
1893 public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
1894 super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
1895 setToolTipText(value.toString());
1896 return this;
1897 }
1898 }
1899
1900 /** Wrap a ElementWrapper so we get its name when we ask for toString(), not its identifier. */
1901 private class NameElementWrapperEntry
1902 implements Comparable {
1903 private ElementWrapper element_wrapper = null;
1904 public NameElementWrapperEntry(Object object) {
1905 this.element_wrapper = (ElementWrapper) object;
1906 }
1907 public int compareTo(Object object) {
1908 return element_wrapper.compareTo(object);
1909 }
1910 public boolean equals(Object object) {
1911 return element_wrapper.equals(object);
1912 }
1913 public String toString() {
1914 return element_wrapper.getName();
1915 }
1916 }
1917}
Note: See TracBrowser for help on using the repository browser.