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

Last change on this file since 8231 was 8231, checked in by mdewsnip, 20 years ago

Replaced all "Gatherer.config" with "Configuration".

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