source: trunk/gli/src/org/greenstone/gatherer/gems/GEMS.java@ 8270

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

Source files for the Greenstone Editor for Metadata Sets (GEMS). This is currently just the old MetadataEditorManager, modified to run stand-alone. It will be substantially improved by Attila Aros.

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