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

Last change on this file since 6042 was 6042, checked in by jmt12, 20 years ago

All typed in values are correctly handled by the various Codec transforms

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