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

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

JScrollPane now right aligned for right aligned languages

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