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

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

Changed text handling to use Dictionary.get rather than Dictionary.setText or Dictionary.registerBoth etc. also removed mnemonics cos they suck for other languages.

  • Property svn:keywords set to Author Date Id Revision
File size: 22.7 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
187 JPanel button_pane_3 = new JPanel();
188 add_button = new GLIButton(Dictionary.get("CDM.SubcollectionManager.Add"), Dictionary.get("CDM.SubcollectionManager.Add_Tooltip"));
189 add_button.setEnabled(false);
190
191 remove_button = new GLIButton(Dictionary.get("CDM.SubcollectionManager.Remove"), Dictionary.get("CDM.SubcollectionManager.Remove_Tooltip"));
192 remove_button.setEnabled(false);
193
194 update_button = new GLIButton(Dictionary.get("CDM.SubcollectionManager.Replace"), Dictionary.get("CDM.SubcollectionManager.Replace_Tooltip"));
195 update_button.setEnabled(false);
196
197 JPanel button_pane = new JPanel();
198 JPanel button_pane_1 = new JPanel();
199 include_button = new JRadioButton(Dictionary.get("CDM.SubcollectionManager.Include"));
200 include_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
201 include_button.setOpaque(false);
202
203 exclude_button = new JRadioButton(Dictionary.get("CDM.SubcollectionManager.Exclude"));
204 exclude_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
205 exclude_button.setOpaque(false);
206
207 JLabel flags_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Flags"));
208
209 flags_field = new NonWhitespaceField();
210 flags_field.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Flags_Tooltip"));
211
212 JPanel inclusive_pane = new JPanel();
213 JLabel inclusive_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Inclusive"));
214
215 JLabel match_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Match"));
216
217 match_field = new JTextField();
218 match_field.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Match_Tooltip"));
219
220 JLabel name_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Name"));
221
222 name_field = new NonWhitespaceField();
223 name_field.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Name_Tooltip"));
224
225 JLabel source_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Source"));
226
227 ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
228 Vector source_model = new Vector(every_metadata_set_element);
229 source_model.add(0, StaticStrings.FILENAME_STR);
230 source_combobox = new JComboBox(source_model);
231 source_combobox.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Source_Tooltip"));
232
233 subcollection_list = new JList(model);
234 subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
235 JPanel subcollection_pane = new JPanel();
236 ButtonGroup bg = new ButtonGroup();
237 bg.add(include_button);
238 bg.add(exclude_button);
239 include_button.setSelected(true);
240 JPanel subcollection_list_pane = new JPanel();
241 JLabel subcollection_list_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Assigned"));
242
243 // Create a message pane which explains why these controls are not currently active
244 JPanel message_pane = new JPanel();
245 String args[] = new String[3];
246 args[0] = Configuration.getModeAsString();
247 args[1] = Dictionary.get("Preferences.Mode.Systems");
248 args[2] = Dictionary.get("Preferences.Mode.Expert");
249 JTextArea message_textarea = new JTextArea(Dictionary.get("CDM.SubcollectionManager.Partitions_Disabled", args));
250
251 message_textarea.setEditable(false);
252 message_textarea.setHighlighter(null); // Prevent highlighting
253 message_textarea.setLineWrap(true);
254 message_textarea.setOpaque(false); // Make it transparent
255 message_textarea.setWrapStyleWord(true);
256
257 // Add listeners
258 SubCollectionChangeListener cl = new SubCollectionChangeListener();
259 add_button.addActionListener(new AddSubCollectionListener());
260 add_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
261 remove_button.addActionListener(new RemoveSubCollectionListener());
262 remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
263 update_button.addActionListener(new UpdateSubCollectionListener());
264 update_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
265 exclude_button.addActionListener(cl);
266 include_button.addActionListener(cl);
267 source_combobox.addActionListener(cl);
268 flags_field.getDocument().addDocumentListener(cl);
269 match_field.getDocument().addDocumentListener(cl);
270 name_field.getDocument().addDocumentListener(cl);
271 subcollection_list.addListSelectionListener(new SubCollectionListListener());
272
273 inclusive_pane.setLayout(new GridLayout());
274 inclusive_pane.add(include_button);
275 inclusive_pane.add(exclude_button);
276
277 button_pane_1.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
278 button_pane_1.setLayout(new GridLayout(5, 2));
279 button_pane_1.add(name_label);
280 button_pane_1.add(name_field);
281 button_pane_1.add(source_label);
282 button_pane_1.add(source_combobox);
283 button_pane_1.add(match_label);
284 button_pane_1.add(match_field);
285 button_pane_1.add(inclusive_label);
286 button_pane_1.add(inclusive_pane);
287 button_pane_1.add(flags_label);
288 button_pane_1.add(flags_field);
289
290 button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
291 button_pane_3.setLayout(new GridLayout(1,3));
292 button_pane_3.add(add_button);
293 button_pane_3.add(update_button);
294 button_pane_3.add(remove_button);
295
296 button_pane.setLayout(new BorderLayout());
297 button_pane.add(button_pane_1, BorderLayout.CENTER);
298 button_pane.add(button_pane_3, BorderLayout.SOUTH);
299
300 subcollection_list_pane.setLayout(new BorderLayout());
301 subcollection_list_pane.add(subcollection_list_label, BorderLayout.NORTH);
302 subcollection_list_pane.add(new JScrollPane(subcollection_list), BorderLayout.CENTER);
303 subcollection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
304 subcollection_pane.setLayout(new BorderLayout());
305 subcollection_pane.add(subcollection_list_pane, BorderLayout.CENTER);
306 subcollection_pane.add(button_pane, BorderLayout.SOUTH);
307
308 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subcollection_Controls"), subcollection_pane);
309 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subindex_Controls"), (JPanel) CollectionDesignManager.subcollectionindex_manager.getControls());
310 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Language_Controls"), (JPanel) CollectionDesignManager.language_manager.getControls());
311
312 message_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
313 message_pane.setLayout(new GridLayout(3,1,0,0));
314 message_pane.add(new JPanel());
315 message_pane.add(message_textarea);
316 message_pane.add(new JPanel());
317
318 border_pane.setLayout(card_layout);
319 if(Configuration.getMode() > Configuration.LIBRARIAN_MODE) {
320 border_pane.add(tabbed_pane, ENABLED_CONTROLS);
321 border_pane.add(message_pane, DISABLED_CONTROLS);
322 }
323 else {
324 border_pane.add(message_pane, DISABLED_CONTROLS);
325 border_pane.add(tabbed_pane, ENABLED_CONTROLS);
326 }
327
328 setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
329 setLayout(new BorderLayout());
330 add(header_pane, BorderLayout.NORTH);
331 add(border_pane, BorderLayout.CENTER);
332 }
333
334 /** Method to unregister any listeners to avoid memory leaks.
335 */
336 public void destroy() {
337 }
338
339 public void gainFocus() {
340 // Rebuild the sources combobox
341 ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
342 Vector source_model = new Vector(every_metadata_set_element);
343 source_model.add(0, "Filename"); // Add filename as a possible source.
344 source_combobox.setModel(new DefaultComboBoxModel(source_model));
345 }
346
347 public void loseFocus() {
348 }
349
350 /** 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.
351 * @param mode the new mode as an int
352 */
353 public void modeChanged(int mode) {
354 if(mode > Configuration.LIBRARIAN_MODE) {
355 card_layout.show(border_pane, ENABLED_CONTROLS);
356 }
357 else {
358 card_layout.show(border_pane, DISABLED_CONTROLS);
359 }
360 }
361
362 public void stateChanged(ChangeEvent event)
363 {
364 if (tabbed_pane.getSelectedIndex() == 1) {
365 CollectionDesignManager.subcollectionindex_manager.getControls().gainFocus();
366 }
367 if (tabbed_pane.getSelectedIndex() == 2) {
368 CollectionDesignManager.language_manager.getControls().gainFocus();
369 }
370 }
371
372 /** 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. */
373 private class AddSubCollectionListener
374 implements ActionListener {
375 /** 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.
376 * @param event An <strong>ActionEvent</strong> containing information about the event.
377 * @see org.greenstone.gatherer.cdm.Subcollection
378 */
379 public void actionPerformed(ActionEvent event) {
380 String name = name_field.getText();
381 String source = null;
382 Object object = source_combobox.getSelectedItem();
383 if (object instanceof MetadataElement) {
384 MetadataElement metadata_element = (MetadataElement) object;
385 source = metadata_element.getFullName();
386 }
387 else {
388 source = object.toString();
389 }
390 String pattern = match_field.getText();
391 String flags = flags_field.getText();
392 if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
393 Subcollection subcollection = new Subcollection(name, include_button.isSelected(), source, pattern, flags);
394 addSubcollection(subcollection);
395 // Change the selection to the new subcollection
396 subcollection_list.setSelectedValue(subcollection, true);
397 }
398 add_button.setEnabled(false);
399 }
400 }
401
402 /** 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. */
403 private class SubCollectionChangeListener
404 implements DocumentListener, ActionListener {
405 /** 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.
406 * @param event An <strong>ActionEvent</strong> containing information about the event.
407 */
408 public void actionPerformed(ActionEvent event) {
409 validateAdd();
410 }
411
412 public void changedUpdate(DocumentEvent event) {
413 validateAdd();
414 }
415
416 public void insertUpdate(DocumentEvent event) {
417 validateAdd();
418
419 }
420
421 public void removeUpdate(DocumentEvent event) {
422 validateAdd();
423 }
424
425 /** Method to validate the current subcollection editor values, and enable or disable controls (add button) based on said values. */
426 private void validateAdd() {
427 if(name_field.getText().length() > 0 && match_field.getText().length() > 0) {
428 if (getSubcollection(name_field.getText()) == null) {
429 add_button.setEnabled(true);
430 } else {
431 add_button.setEnabled(false);
432 }
433 }
434 else {
435 add_button.setEnabled(false);
436 }
437 }
438 }
439
440 /** 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. */
441 private class RemoveSubCollectionListener
442 implements ActionListener {
443 /** 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.
444 * @param event An <strong>ActionEvent</strong> containing information about the event.
445 * @see org.greenstone.gatherer.cdm.Subcollection
446 */
447 public void actionPerformed(ActionEvent event) {
448 if(!subcollection_list.isSelectionEmpty()) {
449 Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
450 removeSubcollection(subcollection);
451 // And remove subcollection indexes dependant on this subcollection
452 CollectionDesignManager.subcollectionindex_manager.removeSubcollectionIndexes(subcollection);
453 }
454 remove_button.setEnabled(false);
455 }
456 }
457
458 private class UpdateSubCollectionListener
459 implements ActionListener {
460 public void actionPerformed(ActionEvent event) {
461 if(!subcollection_list.isSelectionEmpty()) {
462 Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
463 String name = name_field.getText();
464 String source = null;
465 Object object = source_combobox.getSelectedItem();
466 if (object instanceof MetadataElement) {
467 MetadataElement metadata_element = (MetadataElement) object;
468 source = metadata_element.getFullName();
469 }
470 else {
471 source = object.toString();
472 }
473 String pattern = match_field.getText();
474 String flags = flags_field.getText();
475 if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
476 updateSubcollection(subcollection, name, include_button.isSelected(), source, pattern, flags);
477 }
478 }
479 }
480 }
481
482 /** This class listens for selections in the list on the subcollections pane of the SubcollectionManager, and updates the controls as necessary to reflect selection. */
483 private class SubCollectionListListener
484 implements ListSelectionListener {
485 /** 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.
486 * @param event A <strong>ListSelectionEvent</strong> containing information related to this event.
487 * @see org.greenstone.gatherer.cdm.Subcollection
488 */
489 public void valueChanged(ListSelectionEvent event) {
490 // Wait until the event stabilises to avoid processing it multiple times
491 if (event.getValueIsAdjusting() == true) {
492 return;
493 }
494 // Now the entry
495 if(!subcollection_list.isSelectionEmpty()) {
496 Subcollection subcollection = (Subcollection) subcollection_list.getSelectedValue();
497 flags_field.setText(subcollection.getFlags());
498 include_button.setSelected(subcollection.isInclusive());
499 exclude_button.setSelected(!subcollection.isInclusive());
500 match_field.setText(subcollection.getPattern());
501 name_field.setText(subcollection.getName());
502 String s = subcollection.getSource();
503 int pos = 0;
504 Object value = source_combobox.getItemAt(pos);
505 //ystem.err.println("Search for: " + s);
506 while (value != null) {
507 if (value instanceof MetadataElement) {
508 MetadataElement metadata_element = (MetadataElement) value;
509 String metadata_element_name = metadata_element.getFullName();
510 //ystem.err.print("Compare to: " + e_name);
511 if (metadata_element_name.equals(s)) {
512 source_combobox.setSelectedIndex(pos);
513 value = null;
514 //ystem.err.println(" - Match");
515 }
516 else {
517 pos++;
518 value = source_combobox.getItemAt(pos);
519 //ystem.err.println(" - Fail");
520 }
521 }
522 else if(value.toString().equals(s)) {
523 source_combobox.setSelectedIndex(pos);
524 value = null;
525 }
526 else {
527 pos++;
528 value = source_combobox.getItemAt(pos);
529 }
530 }
531 // Can't add one thats already there.
532 add_button.setEnabled(false);
533 // You can update or remove it though...
534 remove_button.setEnabled(true);
535 update_button.setEnabled(true);
536 }
537 else {
538 flags_field.setText("");
539 include_button.setSelected(true);
540 match_field.setText("");
541 name_field.setText("");
542 source_combobox.setSelectedIndex(0);
543 remove_button.setEnabled(false);
544 update_button.setEnabled(false);
545 }
546 }
547 }
548 }
549}
Note: See TracBrowser for help on using the repository browser.