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

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

As part of setting up modes we also added the ability to programatically access the MEM from within design view

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