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

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

Replaced all Gatherer.print* with DebugStream.print*.

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