source: trunk/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java@ 11031

Last change on this file since 11031 was 11031, checked in by kjdon, 18 years ago

removed instructions, changed title to be the same string as in the contents, and use a new class DesignPaneHeader to create teh header which has title and help button

  • Property svn:keywords set to Author Date Id Revision
File size: 23.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
29
30import java.awt.*;
31import java.awt.event.*;
32import java.util.*;
33import javax.swing.*;
34import javax.swing.event.*;
35import org.greenstone.gatherer.Configuration;
36import org.greenstone.gatherer.DebugStream;
37import org.greenstone.gatherer.Dictionary;
38import org.greenstone.gatherer.Gatherer;
39import org.greenstone.gatherer.gui.DesignPaneHeader;
40import org.greenstone.gatherer.gui.GLIButton;
41import org.greenstone.gatherer.gui.NonWhitespaceField;
42import org.greenstone.gatherer.metadata.MetadataElement;
43import org.greenstone.gatherer.metadata.MetadataSetManager;
44import org.greenstone.gatherer.util.StaticStrings;
45import org.w3c.dom.*;
46
47/** This class maintains a list of subcollections within our collection.
48 * @author John Thompson, Greenstone Digital Library, University of Waikato
49 * @version 2.4
50 */
51public class SubcollectionManager
52 extends DOMProxyListModel {
53
54 static final private String DISABLED_CONTROLS = "Disabled";
55 static final private String ENABLED_CONTROLS = "Normal";
56 static final private String CLASS_DICTIONARY_NAME = "CDM.SubcollectionManager.";
57
58 /** The controls used to edit the settings of this manager. */
59 private Control controls = null;
60
61 private DOMProxyListModel model;
62
63 /** Constructor.
64 * @see org.greenstone.gatherer.Gatherer
65 * @see org.greenstone.gatherer.cdm.CollectionConfiguration
66 * @see org.greenstone.gatherer.cdm.CollectionDesignManager
67 * @see org.greenstone.gatherer.cdm.DOMProxyListModel
68 * @see org.greenstone.gatherer.cdm.Subcollection
69 */
70 public SubcollectionManager() {
71 super(CollectionDesignManager.collect_config.getDocumentElement(), StaticStrings.SUBCOLLECTION_ELEMENT, new Subcollection());
72 DebugStream.println("SubcollectionManager: " + getSize() + " subcollections parsed.");
73 this.model = this;
74 }
75
76 /** Method to add a new subcollection.
77 * @param subcollection the Subcollection to add
78 * @see org.greenstone.gatherer.Gatherer
79 * @see org.greenstone.gatherer.cdm.CollectionConfiguration
80 * @see org.greenstone.gatherer.cdm.DOMProxyListModel
81 * @see org.greenstone.gatherer.collection.CollectionManager
82 */
83 private void addSubcollection(Subcollection subcollection) {
84 if(!contains(subcollection)) {
85 Element element = subcollection.getElement();
86 // Locate where we should insert this new subcollection.
87 Node target_node = CollectionConfiguration.findInsertionPoint(element);
88 // Failing that we insert immediately after a language string
89 add(root, subcollection, target_node);
90 Gatherer.c_man.configurationChanged();
91 }
92 }
93
94 public void destroy() {
95 if(controls != null) {
96 controls.destroy();
97 controls = null;
98 }
99 }
100
101 /** Method to retrieve the controls for this manager.
102 * @return the Control used to edit the subcollection data
103 */
104 public Control getControls() {
105 if(controls == null) {
106 controls = new SubcollectionControl();
107 }
108 return controls;
109 }
110
111 /** Method to retrieve a certain subcollection by its name.
112 * @param name a String which is used as the key for finding the matching subcollection
113 * @return the requested Subcollection or null if no such subcollection exists.
114 */
115 private Subcollection getSubcollection(String name) {
116 Subcollection result = null;
117 int size = getSize();
118 for(int i = 0; i < size; i++) {
119 Subcollection subcollection = (Subcollection) getElementAt(i);
120 if(subcollection.getName().equals(name)) {
121 result = subcollection;
122 }
123 }
124 return result;
125 }
126
127
128 /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
129 * @param mode the new mode as an int
130 */
131 public void modeChanged(int mode) {
132 if(controls != null) {
133 ((SubcollectionControl)controls).modeChanged(mode);
134 }
135 }
136
137 /** Method to remove the given subcollection.
138 * @param subcollection the Subcollection you want to remove
139 * @see org.greenstone.gatherer.Gatherer
140 * @see org.greenstone.gatherer.collection.CollectionManager
141 */
142 private void removeSubcollection(Subcollection subcollection) {
143 remove(subcollection);
144 Gatherer.c_man.configurationChanged();
145 }
146
147 private void updateSubcollection(Subcollection subcollection, String name, boolean include, String source, String pattern, String flags) {
148 subcollection.setFlags(flags);
149 subcollection.setInclusive(include);
150 subcollection.setName(name);
151 subcollection.setPattern(pattern);
152 subcollection.setSource(source);
153 refresh(subcollection);
154 Gatherer.c_man.configurationChanged();
155 }
156
157 /** This class creates a JPanel containing serveral more controls used for editing subcollection information. */
158 private class SubcollectionControl
159 extends JPanel
160 implements Control, ChangeListener
161 {
162 private CardLayout card_layout;
163 private JButton add_button;
164 private JButton remove_button;
165 private JButton update_button;
166 private JComboBox source_combobox;
167 private JList subcollection_list;
168 private JPanel border_pane;
169 private JTabbedPane tabbed_pane;
170 private JTextField flags_field;
171 private JTextField match_field;
172 private JTextField name_field;
173 private JRadioButton exclude_button;
174 private JRadioButton include_button;
175
176 /** Constructor */
177 public SubcollectionControl() {
178 // Create
179 JPanel header_pane = new DesignPaneHeader("CDM.GUI.Subcollections", "partitionindexes");
180
181 border_pane = new JPanel();
182 card_layout = new CardLayout();
183
184 tabbed_pane = new JTabbedPane();
185 tabbed_pane.addChangeListener(this);
186 JLabel title = new JLabel();
187 title.setHorizontalAlignment(JLabel.CENTER);
188 Dictionary.registerText(title, "CDM.SubcollectionManager.Title");
189
190 JPanel button_pane_3 = new JPanel();
191 add_button = new GLIButton();
192 add_button.setMnemonic(KeyEvent.VK_A);
193 add_button.setEnabled(false);
194 Dictionary.registerBoth(add_button, "CDM.SubcollectionManager.Add", "CDM.SubcollectionManager.Add_Tooltip");
195 remove_button = new GLIButton();
196 remove_button.setMnemonic(KeyEvent.VK_R);
197 remove_button.setEnabled(false);
198 Dictionary.registerBoth(remove_button, "CDM.SubcollectionManager.Remove", "CDM.SubcollectionManager.Remove_Tooltip");
199 update_button = new GLIButton();
200 update_button.setMnemonic(KeyEvent.VK_C);
201 update_button.setEnabled(false);
202 Dictionary.registerBoth(update_button, "CDM.SubcollectionManager.Replace", "CDM.SubcollectionManager.Replace_Tooltip");
203
204 JPanel button_pane = new JPanel();
205 JPanel button_pane_1 = new JPanel();
206 include_button = new JRadioButton();
207 include_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
208 include_button.setMnemonic(KeyEvent.VK_I);
209 include_button.setOpaque(false);
210 Dictionary.registerText(include_button, "CDM.SubcollectionManager.Include");
211 exclude_button = new JRadioButton();
212 exclude_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
213 exclude_button.setMnemonic(KeyEvent.VK_X);
214 exclude_button.setOpaque(false);
215 Dictionary.registerText(exclude_button, "CDM.SubcollectionManager.Exclude");
216
217 JLabel flags_label = new JLabel();
218 Dictionary.registerText(flags_label, "CDM.SubcollectionManager.Flags");
219 flags_field = new NonWhitespaceField();
220 Dictionary.registerTooltip(flags_field, "CDM.SubcollectionManager.Flags_Tooltip");
221
222 JPanel inclusive_pane = new JPanel();
223 JLabel inclusive_label = new JLabel();
224 Dictionary.registerText(inclusive_label, "CDM.SubcollectionManager.Inclusive");
225
226 JLabel match_label = new JLabel();
227 Dictionary.registerText(match_label, "CDM.SubcollectionManager.Match");
228 match_field = new JTextField();
229 Dictionary.registerTooltip(match_field, "CDM.SubcollectionManager.Match_Tooltip");
230
231 JLabel name_label = new JLabel();
232 Dictionary.registerText(name_label, "CDM.SubcollectionManager.Name");
233 name_field = new NonWhitespaceField();
234 Dictionary.registerTooltip(name_field, "CDM.SubcollectionManager.Name_Tooltip");
235
236 JLabel source_label = new JLabel();
237 Dictionary.registerText(source_label, "CDM.SubcollectionManager.Source");
238 ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
239 Vector source_model = new Vector(every_metadata_set_element);
240 source_model.add(0, StaticStrings.FILENAME_STR);
241 source_combobox = new JComboBox(source_model);
242 Dictionary.registerTooltip(source_combobox, "CDM.SubcollectionManager.Source_Tooltip");
243
244 subcollection_list = new JList(model);
245 subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
246 JPanel subcollection_pane = new JPanel();
247 ButtonGroup bg = new ButtonGroup();
248 bg.add(include_button);
249 bg.add(exclude_button);
250 include_button.setSelected(true);
251 JPanel subcollection_list_pane = new JPanel();
252 JLabel subcollection_list_label = new JLabel();
253 Dictionary.registerText(subcollection_list_label, "CDM.SubcollectionManager.Assigned");
254
255 // Create a message pane which explains why these controls are not currently active
256 JPanel message_pane = new JPanel();
257 String args[] = new String[3];
258 args[0] = Configuration.getModeAsString();
259 args[1] = Dictionary.get("Preferences.Mode.Systems");
260 args[2] = Dictionary.get("Preferences.Mode.Expert");
261 JTextArea message_textarea = new JTextArea();
262 Dictionary.registerText(message_textarea, "CDM.SubcollectionManager.Partitions_Disabled", args);
263 message_textarea.setEditable(false);
264 message_textarea.setHighlighter(null); // Prevent highlighting
265 message_textarea.setLineWrap(true);
266 message_textarea.setOpaque(false); // Make it transparent
267 message_textarea.setWrapStyleWord(true);
268
269 // Add listeners
270 SubCollectionChangeListener cl = new SubCollectionChangeListener();
271 add_button.addActionListener(new AddSubCollectionListener());
272 add_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
273 remove_button.addActionListener(new RemoveSubCollectionListener());
274 remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
275 update_button.addActionListener(new UpdateSubCollectionListener());
276 update_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
277 exclude_button.addActionListener(cl);
278 include_button.addActionListener(cl);
279 source_combobox.addActionListener(cl);
280 flags_field.getDocument().addDocumentListener(cl);
281 match_field.getDocument().addDocumentListener(cl);
282 name_field.getDocument().addDocumentListener(cl);
283 subcollection_list.addListSelectionListener(new SubCollectionListListener());
284
285 inclusive_pane.setLayout(new GridLayout());
286 inclusive_pane.add(include_button);
287 inclusive_pane.add(exclude_button);
288
289 button_pane_1.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
290 button_pane_1.setLayout(new GridLayout(5, 2));
291 button_pane_1.add(name_label);
292 button_pane_1.add(name_field);
293 button_pane_1.add(source_label);
294 button_pane_1.add(source_combobox);
295 button_pane_1.add(match_label);
296 button_pane_1.add(match_field);
297 button_pane_1.add(inclusive_label);
298 button_pane_1.add(inclusive_pane);
299 button_pane_1.add(flags_label);
300 button_pane_1.add(flags_field);
301
302 button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
303 button_pane_3.setLayout(new GridLayout(1,3));
304 button_pane_3.add(add_button);
305 button_pane_3.add(update_button);
306 button_pane_3.add(remove_button);
307
308 button_pane.setLayout(new BorderLayout());
309 button_pane.add(button_pane_1, BorderLayout.CENTER);
310 button_pane.add(button_pane_3, BorderLayout.SOUTH);
311
312 subcollection_list_pane.setLayout(new BorderLayout());
313 subcollection_list_pane.add(subcollection_list_label, BorderLayout.NORTH);
314 subcollection_list_pane.add(new JScrollPane(subcollection_list), BorderLayout.CENTER);
315 subcollection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
316 subcollection_pane.setLayout(new BorderLayout());
317 subcollection_pane.add(subcollection_list_pane, BorderLayout.CENTER);
318 subcollection_pane.add(button_pane, BorderLayout.SOUTH);
319
320 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subcollection_Controls"), subcollection_pane);
321 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subindex_Controls"), (JPanel) CollectionDesignManager.subcollectionindex_manager.getControls());
322 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Language_Controls"), (JPanel) CollectionDesignManager.language_manager.getControls());
323
324 message_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
325 message_pane.setLayout(new GridLayout(3,1,0,0));
326 message_pane.add(new JPanel());
327 message_pane.add(message_textarea);
328 message_pane.add(new JPanel());
329
330 border_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
331 border_pane.setLayout(card_layout);
332 if(Configuration.getMode() > Configuration.LIBRARIAN_MODE) {
333 border_pane.add(tabbed_pane, ENABLED_CONTROLS);
334 border_pane.add(message_pane, DISABLED_CONTROLS);
335 }
336 else {
337 border_pane.add(message_pane, DISABLED_CONTROLS);
338 border_pane.add(tabbed_pane, ENABLED_CONTROLS);
339 }
340
341 setLayout(new BorderLayout());
342 add(header_pane, BorderLayout.NORTH);
343 add(border_pane, BorderLayout.CENTER);
344 }
345
346 /** Method to unregister any listeners to avoid memory leaks.
347 */
348 public void destroy() {
349 }
350
351 public void gainFocus() {
352 // Rebuild the sources combobox
353 ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
354 Vector source_model = new Vector(every_metadata_set_element);
355 source_model.add(0, "Filename"); // Add filename as a possible source.
356 source_combobox.setModel(new DefaultComboBoxModel(source_model));
357 }
358
359 public void loseFocus() {
360 }
361
362 /** Called when the detail mode has changed which in turn controls if any of the partition controls are visible, or if they are instead replaced with a message explaining why they are not.
363 * @param mode the new mode as an int
364 */
365 public void modeChanged(int mode) {
366 if(mode > Configuration.LIBRARIAN_MODE) {
367 card_layout.show(border_pane, ENABLED_CONTROLS);
368 }
369 else {
370 card_layout.show(border_pane, DISABLED_CONTROLS);
371 }
372 }
373
374 public void stateChanged(ChangeEvent event)
375 {
376 if (tabbed_pane.getSelectedIndex() == 1) {
377 CollectionDesignManager.subcollectionindex_manager.getControls().gainFocus();
378 }
379 if (tabbed_pane.getSelectedIndex() == 2) {
380 CollectionDesignManager.language_manager.getControls().gainFocus();
381 }
382 }
383
384 /** Listens for actions apon the 'add' button in the SubcollectionManager controls, and if detected calls the addSubcollection method of the manager with a newly created subcollection. */
385 private class AddSubCollectionListener
386 implements ActionListener {
387 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we wish to retrieve information from the various edit controls, and if we have sufficient data to build a new subcollection do so.
388 * @param event An <strong>ActionEvent</strong> containing information about the event.
389 * @see org.greenstone.gatherer.cdm.Subcollection
390 */
391 public void actionPerformed(ActionEvent event) {
392 String name = name_field.getText();
393 String source = null;
394 Object object = source_combobox.getSelectedItem();
395 if (object instanceof MetadataElement) {
396 MetadataElement metadata_element = (MetadataElement) object;
397 source = metadata_element.getFullName();
398 }
399 else {
400 source = object.toString();
401 }
402 String pattern = match_field.getText();
403 String flags = flags_field.getText();
404 if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
405 Subcollection subcollection = new Subcollection(name, include_button.isSelected(), source, pattern, flags);
406 addSubcollection(subcollection);
407 // Change the selection to the new subcollection
408 subcollection_list.setSelectedValue(subcollection, true);
409 }
410 add_button.setEnabled(false);
411 }
412 }
413
414 /** This class listens for any key entry in a text field, selection change in a combobox or button click, and updates a subcollection as appropriate. Its also convenient to use this class to test if the add button should be active yet. */
415 private class SubCollectionChangeListener
416 implements DocumentListener, ActionListener {
417 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to record that somethings changed, then validate the controls.
418 * @param event An <strong>ActionEvent</strong> containing information about the event.
419 */
420 public void actionPerformed(ActionEvent event) {
421 validateAdd();
422 }
423
424 public void changedUpdate(DocumentEvent event) {
425 validateAdd();
426 }
427
428 public void insertUpdate(DocumentEvent event) {
429 validateAdd();
430
431 }
432
433 public void removeUpdate(DocumentEvent event) {
434 validateAdd();
435 }
436
437 /** Method to validate the current subcollection editor values, and enable or disable controls (add button) based on said values. */
438 private void validateAdd() {
439 if(name_field.getText().length() > 0 && match_field.getText().length() > 0) {
440 if (getSubcollection(name_field.getText()) == null) {
441 add_button.setEnabled(true);
442 } else {
443 add_button.setEnabled(false);
444 }
445 }
446 else {
447 add_button.setEnabled(false);
448 }
449 }
450 }
451
452 /** Listens for actions apon the 'remove' button in the SubcollectionManager controls, and if detected calls the remove method of the manager with the SubIndex selected for removal. */
453 private class RemoveSubCollectionListener
454 implements ActionListener {
455 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subcolleciton selected, and if so remove both it and any subindexes based on it.
456 * @param event An <strong>ActionEvent</strong> containing information about the event.
457 * @see org.greenstone.gatherer.cdm.Subcollection
458 */
459 public void actionPerformed(ActionEvent event) {
460 if(!subcollection_list.isSelectionEmpty()) {
461 Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
462 removeSubcollection(subcollection);
463 // And remove subcollection indexes dependant on this subcollection
464 CollectionDesignManager.subcollectionindex_manager.removeSubcollectionIndexes(subcollection);
465 }
466 remove_button.setEnabled(false);
467 }
468 }
469
470 private class UpdateSubCollectionListener
471 implements ActionListener {
472 public void actionPerformed(ActionEvent event) {
473 if(!subcollection_list.isSelectionEmpty()) {
474 Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
475 String name = name_field.getText();
476 String source = null;
477 Object object = source_combobox.getSelectedItem();
478 if (object instanceof MetadataElement) {
479 MetadataElement metadata_element = (MetadataElement) object;
480 source = metadata_element.getFullName();
481 }
482 else {
483 source = object.toString();
484 }
485 String pattern = match_field.getText();
486 String flags = flags_field.getText();
487 if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
488 updateSubcollection(subcollection, name, include_button.isSelected(), source, pattern, flags);
489 }
490 }
491 }
492 }
493
494 /** This class listens for selections in the list on the subcollections pane of the SubcollectionManager, and updates the controls as necessary to reflect selection. */
495 private class SubCollectionListListener
496 implements ListSelectionListener {
497 /** Any implementation of ListSelectionListener must include this method so we can be informed when the selection changes. In this case we want to execute any changes the users made to the entry, then update the controls with details of the new selection.
498 * @param event A <strong>ListSelectionEvent</strong> containing information related to this event.
499 * @see org.greenstone.gatherer.cdm.Subcollection
500 */
501 public void valueChanged(ListSelectionEvent event) {
502 // Wait until the event stabilises to avoid processing it multiple times
503 if (event.getValueIsAdjusting() == true) {
504 return;
505 }
506 // Now the entry
507 if(!subcollection_list.isSelectionEmpty()) {
508 Subcollection subcollection = (Subcollection) subcollection_list.getSelectedValue();
509 flags_field.setText(subcollection.getFlags());
510 include_button.setSelected(subcollection.isInclusive());
511 exclude_button.setSelected(!subcollection.isInclusive());
512 match_field.setText(subcollection.getPattern());
513 name_field.setText(subcollection.getName());
514 String s = subcollection.getSource();
515 int pos = 0;
516 Object value = source_combobox.getItemAt(pos);
517 //ystem.err.println("Search for: " + s);
518 while (value != null) {
519 if (value instanceof MetadataElement) {
520 MetadataElement metadata_element = (MetadataElement) value;
521 String metadata_element_name = metadata_element.getFullName();
522 //ystem.err.print("Compare to: " + e_name);
523 if (metadata_element_name.equals(s)) {
524 source_combobox.setSelectedIndex(pos);
525 value = null;
526 //ystem.err.println(" - Match");
527 }
528 else {
529 pos++;
530 value = source_combobox.getItemAt(pos);
531 //ystem.err.println(" - Fail");
532 }
533 }
534 else if(value.toString().equals(s)) {
535 source_combobox.setSelectedIndex(pos);
536 value = null;
537 }
538 else {
539 pos++;
540 value = source_combobox.getItemAt(pos);
541 }
542 }
543 // Can't add one thats already there.
544 add_button.setEnabled(false);
545 // You can update or remove it though...
546 remove_button.setEnabled(true);
547 update_button.setEnabled(true);
548 }
549 else {
550 flags_field.setText("");
551 include_button.setSelected(true);
552 match_field.setText("");
553 name_field.setText("");
554 source_combobox.setSelectedIndex(0);
555 remove_button.setEnabled(false);
556 update_button.setEnabled(false);
557 }
558 }
559 }
560 }
561}
Note: See TracBrowser for help on using the repository browser.