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

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

Removed all occurrences of classes explicitly importing other classes in the same package.

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