source: trunk/gli/src/org/greenstone/gatherer/cdm/MetadataSetView.java@ 8231

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

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

  • Property svn:keywords set to Author Date Id Revision
File size: 19.4 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 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29import java.awt.*;
30import java.awt.event.*;
31import java.util.*;
32import javax.swing.*;
33import javax.swing.event.*;
34import org.greenstone.gatherer.Configuration;
35import org.greenstone.gatherer.Dictionary;
36import org.greenstone.gatherer.Gatherer;
37import org.greenstone.gatherer.cdm.CollectionDesignManager;
38import org.greenstone.gatherer.cdm.Control;
39import org.greenstone.gatherer.cdm.ElementWrapper;
40import org.greenstone.gatherer.gui.GLIButton;
41import org.greenstone.gatherer.mem.MetadataEditorManager;
42import org.greenstone.gatherer.msm.MetadataSet;
43import org.greenstone.gatherer.msm.MSMEvent;
44import org.greenstone.gatherer.msm.MSMListener;
45import org.w3c.dom.*;
46
47/** This class only knows how to produce a simple visual representation of the currently imported metadata sets. It is also read-only, so should be fairly straight forward.
48 * @author John Thompson, Greenstone Digital Library, University of Waikato
49 * @version 2.3d
50 */
51public class MetadataSetView
52 extends DynamicListModel
53 implements MSMListener {
54 /** The visual contols used to review the metadata sets. */
55 private Control controls = null;
56 /** A reference to ourselves so our inner classes can refer to us. */
57 private DynamicListModel model = null;
58
59 /** Constructor.
60 */
61 public MetadataSetView() {
62 Gatherer.println("MetadataSetView: Initialized.");
63 model = this;
64 Gatherer.c_man.getCollection().msm.addMSMListener(this);
65 loadMetadataSets();
66 // Build the controls
67 controls = new MetadataSetControl();
68 }
69
70 /** Destructor. Remove any references of this class from persistant objects.
71 * @see org.greenstone.gatherer.Gatherer
72 * @see org.greenstone.gatherer.collection.CollectionManager
73 */
74 public void destroy() {
75 controls.destroy();
76 controls = null;
77 Gatherer.c_man.msm.removeMSMListener(this);
78 model = null;
79 }
80
81 /** Called when an element is changed within a set in the MSM, prompting us to refresh our list of elements being shown.
82 * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change.
83 * @see org.greenstone.gatherer.cdm.MetadataSetView.MetadataSetControl
84 */
85 public void elementChanged(MSMEvent event) {
86 // Get the controls to refresh element list.
87 ((MetadataSetControl)controls).refreshElementList();
88 }
89
90 /** A method for retrieve the controls for this manager.
91 * @see org.greenstone.gatherer.Dictionary
92 * @see org.greenstone.gatherer.gui.Coloring
93 */
94 public Control getControls() {
95 return controls;
96 }
97
98 /** Called when a metadata value has undergone significant change.
99 * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change.
100 */
101 public void metadataChanged(MSMEvent event) {
102 // Couldn't care less.
103 }
104
105 /** Called when a set is added or removed from the MSM.
106 * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change.
107 */
108 public void setChanged(MSMEvent event) {
109 // Reload model.
110 clear();
111 loadMetadataSets();
112 }
113
114
115 /** Prints out the contents of this manager, as they would appear in the collection configuration file.
116 * @return A <strong>String</strong> containing a block of commands.
117 * @see org.greenstone.gatherer.cdm.MetadataSetView.SetWrapper
118 */
119 public String toString() {
120 String text = "";
121 for(int i = 0; i < size(); i++) {
122 SetWrapper set = (SetWrapper)get(i);
123 text = text + set.toString() + "\n";
124 }
125 text = text + "\n";
126 return text;
127 }
128
129 /** Called when a significant change has occured to a value tree for a certain element, however we take no further action.
130 * @param event A <strong>MSMEvent</strong> containing information relevant to the event.
131 */
132 public void valueChanged(MSMEvent event) {
133 }
134
135 /** Retrieves the current list of loaded metadata sets, and builds a list model around them.
136 * @see org.greenstone.gatherer.Gatherer
137 * @see org.greenstone.gatherer.cdm.MetadataSetView.SetWrapper
138 * @see org.greenstone.gatherer.collection.CollectionManager
139 */
140 private void loadMetadataSets() {
141 // We initialize the set_model with wrapped metadata sets. Note that when we call getSets() we also end up adding ourselves as a listener to the metadata set manager.
142 Vector sets = Gatherer.c_man.getCollection().msm.getSets();
143 for(int i = 0; i < sets.size(); i++) {
144 addElement(new SetWrapper((MetadataSet)sets.get(i)));
145 }
146 }
147
148 /** This class creates and lays-out the various controls for reviewing the metadata sets, and their commands as they would appear in the collection configuration file. */
149 private class MetadataSetControl
150 extends JPanel
151 implements Control {
152 /** Listens for clicks upon the configure button, or double clicks from the metadata set list. */
153 private ConfigureActionListener configure_action_listener;
154 /** Opens the MEM and systematically performs as if the add set button were clicked. */
155 private JButton add_button;
156 /** Opens the MEM with the appropriate set open for editing. */
157 private JButton configure_button;
158 /** Opens the MEM and systematically performs as if the remove set button were clicked. */
159 private JButton remove_button;
160 /** The label denoting the element list. */
161 private JLabel element_label = null;
162 /** The label denoting the set list. */
163 private JLabel set_label = null;
164 /** The title of these controls. */
165 private JLabel title = null;
166 /** The list of elements for the choosen set. */
167 private JList element_list = null;
168 /** The list of sets in this collection. */
169 private JList set_list = null;
170 /** The panel onto which all other panels will be placed. */
171 private JPanel central_pane = null;
172 /** The panel onto which the element list will be placed. */
173 private JPanel element_pane = null;
174 /** The panel containing the title and instructions. */
175 private JPanel header_pane = null;
176 /** The panel containing the set list. */
177 private JPanel set_pane = null;
178
179 private JScrollPane element_list_scroll_pane;
180 /** The text area of inline instructions. */
181 private JTextArea instructions = null;
182
183 private ListListener list_listener;
184
185 private MultilingualListCellRenderer element_list_cell_renderer;
186
187 /** The element model for the currently selected set. */
188 private Vector element_model = null;
189
190 /* Constructor.
191 * @see org.greenstone.gatherer.Coloring;
192 * @see org.greenstone.gatherer.Dictionary
193 * @see org.greenstone.gatherer.cdm.MetadataSetView.ListListener
194 */
195 public MetadataSetControl() {
196 // Create visual components
197 central_pane = new JPanel();
198 element_label = new JLabel();
199 element_label.setHorizontalAlignment(JLabel.CENTER);
200 element_label.setOpaque(true);
201 Dictionary.registerText(element_label, "CDM.MetadataSetManager.Elements");
202 element_list_scroll_pane = new JScrollPane();
203 element_list_cell_renderer = new MultilingualListCellRenderer(element_list_scroll_pane);
204 element_list = new JList();
205 element_list_scroll_pane.setViewportView(element_list);
206 element_list.setCellRenderer(element_list_cell_renderer);
207 element_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
208 element_pane = new JPanel();
209 header_pane = new JPanel();
210 instructions = new JTextArea();
211 instructions.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
212 instructions.setEditable(false);
213 instructions.setLineWrap(true);
214 instructions.setRows(6);
215 instructions.setWrapStyleWord(true);
216 Dictionary.registerText(instructions, "CDM.MetadataSetManager.Instructions");
217 set_label = new JLabel();
218 set_label.setHorizontalAlignment(JLabel.CENTER);
219 set_label.setOpaque(true);
220 Dictionary.registerText(set_label, "CDM.MetadataSetManager.Sets");
221 set_list = new JList(model);
222 set_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
223 if(model.size() > 0) {
224 set_list.setSelectedIndex(0);
225 }
226
227 set_pane = new JPanel();
228 title = new JLabel();
229 title.setHorizontalAlignment(JLabel.CENTER);
230 title.setOpaque(true);
231 Dictionary.registerText(title, "CDM.MetadataSetManager.Title");
232
233 JPanel button_pane = new JPanel();
234 add_button = new GLIButton();
235 add_button.setEnabled(true);
236 add_button.setMnemonic(KeyEvent.VK_A);
237 Dictionary.registerBoth(add_button, "CDM.MetadataSetManager.Add", "CDM.MetadataSetManager.Add_Tooltip");
238 configure_button = new GLIButton();
239 configure_button.setEnabled(false);
240 configure_button.setMnemonic(KeyEvent.VK_C);
241 Dictionary.registerBoth(configure_button, "CDM.MetadataSetManager.Configure", "CDM.MetadataSetManager.Configure_Tooltip");
242 remove_button = new GLIButton();
243 remove_button.setEnabled(false);
244 remove_button.setMnemonic(KeyEvent.VK_R);
245 Dictionary.registerBoth(remove_button, "CDM.MetadataSetManager.Remove", "CDM.MetadataSetManager.Remove_Tooltip");
246 configure_action_listener = new ConfigureActionListener();
247 list_listener = new ListListener();
248
249 // Add listeners
250 add_button.addActionListener(new AddButtonListener());
251 configure_button.addActionListener(configure_action_listener);
252 remove_button.addActionListener(new RemoveButtonListener());
253 set_list.addListSelectionListener(list_listener);
254 set_list.addMouseListener(configure_action_listener);
255 // Layout
256 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
257
258 header_pane.setLayout(new BorderLayout());
259 header_pane.add(title, BorderLayout.NORTH);
260 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
261
262 set_pane.setLayout(new BorderLayout());
263 set_pane.add(set_label, BorderLayout.NORTH);
264 set_pane.add(new JScrollPane(set_list), BorderLayout.CENTER);
265
266 element_pane.setLayout(new BorderLayout());
267 element_pane.add(element_label, BorderLayout.NORTH);
268 element_pane.add(element_list_scroll_pane, BorderLayout.CENTER);
269
270 central_pane.setLayout(new GridLayout(2,1));
271 central_pane.add(set_pane);
272 central_pane.add(element_pane);
273
274 button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
275 button_pane.setLayout(new GridLayout(1,3,0,0));
276 button_pane.add(add_button);
277 button_pane.add(configure_button);
278 button_pane.add(remove_button);
279
280 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
281 setLayout(new BorderLayout());
282 add(header_pane, BorderLayout.NORTH);
283 add(central_pane, BorderLayout.CENTER);
284 add(button_pane, BorderLayout.SOUTH);
285 }
286 /** Destructor. */
287 public void destroy() {
288 }
289 /** Update the element list. */
290 public void refreshElementList() {
291 element_list.updateUI();
292 }
293
294 /** Overriden to ensure the instruction area is scrolled to top.
295 */
296 public void gainFocus() {
297 if(instructions != null) {
298 instructions.setCaretPosition(0);
299 }
300 // If no current selection, select first available set
301 if(set_list.isSelectionEmpty() && set_list.getModel().getSize() > 0) {
302 set_list.setSelectedIndex(0);
303 list_listener.valueChanged(new ListSelectionEvent(set_list, 0, 0, true));
304 }
305 }
306
307 public void loseFocus() {
308 }
309
310 /** Listens for clicks on the add button, and actions them accordingly by opening the MEM and clicking add set. */
311 private class AddButtonListener
312 implements ActionListener {
313 /** Called when the add button is clicked.
314 * @param event an ActionEvent containing information about the mouse click
315 * @see org.greenstone.gatherer.Gatherer
316 * @see org.greenstone.gatherer.collection.Collection
317 * @see org.greenstone.gatherer.collection.CollectionManager
318 * @see org.greenstone.gatherer.mem.MetadataEditorManager
319 */
320 public void actionPerformed(ActionEvent event) {
321 Gatherer.c_man.getCollection().msm.editMDS(null, MetadataEditorManager.ADD_SET);
322 }
323 }
324
325 /** Listens for clicks on the configure button or double clicks upon the metadata set list and chains to the MEM as appropriate. */
326 private class ConfigureActionListener
327 extends MouseAdapter
328 implements ActionListener {
329 /** Called when the configure button is clicked.
330 * @param event an ActionEvent containing information about the mouse click
331 */
332 public void actionPerformed(ActionEvent event) {
333 configureSet();
334 }
335
336 /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
337 * @param event a MouseEvent containing information about the mouse click
338 */
339 public void mouseClicked(MouseEvent event) {
340 if(event.getClickCount() == 2 ) {
341 configureSet();
342 }
343 }
344 /** If some set is selected, then open the metadata set manager with the current set selected and expanded
345 * @see org.greenstone.gatherer.Gatherer
346 * @see org.greenstone.gatherer.collection.Collection
347 * @see org.greenstone.gatherer.collection.CollectionManager
348 * @see org.greenstone.gatherer.cdm.MetadataSetView.SetWrapper
349 * @see org.greenstone.gatherer.mem.MetadataEditorManager
350 */
351 private void configureSet() {
352 if(!set_list.isSelectionEmpty()) {
353 MetadataSet set = ((SetWrapper)set_list.getSelectedValue()).getSet();
354 Gatherer.c_man.getCollection().msm.editMDS(set, MetadataEditorManager.NORMAL);
355 }
356 else {
357 configure_button.setEnabled(false);
358 }
359 }
360 }
361
362 private class ListListener
363 implements ListSelectionListener {
364 public void valueChanged(ListSelectionEvent event) {
365 // Wait until we get a stable event
366 if(event.getValueIsAdjusting()) {
367 return;
368 }
369 // Now we can process it
370 if(!set_list.isSelectionEmpty()) {
371 MetadataSet set = ((SetWrapper)set_list.getSelectedValue()).getSet();
372 NodeList elements = set.getElements();
373 element_model = new Vector();
374 for(int i = 0; i < elements.getLength(); i++) {
375 element_model.add(new ElementWrapper(elements.item(i)));
376 }
377 //Collections.sort(element_model);
378 element_list.setListData(element_model);
379 configure_button.setEnabled(true);
380 remove_button.setEnabled(true);
381
382 // Finally check the directionality and scroll as necessary
383 JScrollBar scroll_bar = element_list_scroll_pane.getHorizontalScrollBar();
384 if(element_list_cell_renderer.getDirectionality() == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
385 scroll_bar.setValue(scroll_bar.getMaximum());
386 }
387 else {
388 scroll_bar.setValue(scroll_bar.getMinimum());
389 }
390
391 }
392 else {
393 configure_button.setEnabled(false);
394 remove_button.setEnabled(false);
395 }
396 }
397 }
398
399 /** Listens for clicks on the remove button, and actions them accordingly by opening the MEM and clicking remove set. */
400 private class RemoveButtonListener
401 implements ActionListener {
402 /** Called when the remove button is clicked.
403 * @param event an ActionEvent containing information about the mouse click
404 * @see org.greenstone.gatherer.Gatherer
405 * @see org.greenstone.gatherer.collection.Collection
406 * @see org.greenstone.gatherer.collection.CollectionManager
407 * @see org.greenstone.gatherer.cdm.MetadataSetView.SetWrapper
408 * @see org.greenstone.gatherer.mem.MetadataEditorManager
409 */
410 public void actionPerformed(ActionEvent event) {
411 if(!set_list.isSelectionEmpty()) {
412 MetadataSet set = ((SetWrapper)set_list.getSelectedValue()).getSet();
413 Gatherer.c_man.getCollection().msm.editMDS(set, MetadataEditorManager.REMOVE_SET);
414 }
415 else {
416 remove_button.setEnabled(false);
417 }
418 }
419 }
420
421 private class MultilingualListCellRenderer
422 extends DefaultListCellRenderer {
423 private byte previous_directionality = Character.DIRECTIONALITY_UNDEFINED;
424 private JScrollPane scroll_pane;
425 public MultilingualListCellRenderer(JScrollPane scroll_pane) {
426 super();
427 this.scroll_pane = scroll_pane;
428 }
429
430 public byte getDirectionality() {
431 if(previous_directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT || previous_directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC || previous_directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING || previous_directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE) {
432 return Character.DIRECTIONALITY_RIGHT_TO_LEFT;
433 }
434 else {
435 return Character.DIRECTIONALITY_LEFT_TO_RIGHT;
436 }
437 }
438
439 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
440 JLabel component = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
441 // Determine if the text should be left aligned or right aligned
442 String text = value.toString();
443 int text_index = 0;
444 byte directionality = Character.DIRECTIONALITY_UNDEFINED;
445 while(directionality == Character.DIRECTIONALITY_UNDEFINED && text_index < text.length()) {
446 directionality = Character.getDirectionality(text.charAt(text_index));
447 text_index++;
448 }
449 if(directionality != previous_directionality) {
450 previous_directionality = directionality;
451 if(directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE) {
452 ///ystem.err.println("R2L for: " + text);
453 component.setHorizontalAlignment(JLabel.TRAILING);
454 component.setHorizontalTextPosition(JLabel.TRAILING);
455 component.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
456 //scroll_pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
457 }
458 else {
459 component.setHorizontalAlignment(JLabel.LEADING);
460 component.setHorizontalTextPosition(JLabel.LEADING);
461 ///ystem.err.println("L2R for: " + text);
462 component.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
463 //scroll_pane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
464 }
465 }
466
467 text = null;
468 return component;
469 }
470
471 }
472
473 }
474
475 /** Provides a convience wrapper around a metadata set, that allows it to appear in the <strong>JList</strong> the same way it would in the collection configuration file. */
476 private class SetWrapper {
477 private MetadataSet set = null;
478 public SetWrapper(MetadataSet set) {
479 this.set = set;
480 }
481 public MetadataSet getSet() {
482 return set;
483 }
484 public String toString() {
485 String namespace = set.getNamespace();
486 // Watch out for the greenstone set, with its namespace of ""
487 return "metadataset " + namespace + " \"" + set.getName() + "\"";
488 }
489 }
490}
Note: See TracBrowser for help on using the repository browser.