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

Last change on this file since 13195 was 13195, checked in by kjdon, 17 years ago

quan's changes to remove blue borders around buttons and comboboxes on macs

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