source: trunk/gli/src/org/greenstone/gatherer/cdm/SearchTypeManager.java@ 8002

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

Tightened up many public functions to private.

  • Property svn:keywords set to Author Date Id Revision
File size: 18.5 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29/**************************************************************************************
30 * Written: 16/07/03
31 * Revised:
32 **************************************************************************************/
33import java.awt.*;
34import java.awt.event.*;
35import java.util.*;
36import javax.swing.*;
37import javax.swing.event.*;
38import org.greenstone.gatherer.Dictionary;
39import org.greenstone.gatherer.Gatherer;
40import org.greenstone.gatherer.cdm.CollectionConfiguration;
41import org.greenstone.gatherer.cdm.CollectionDesignManager;
42import org.greenstone.gatherer.cdm.Control;
43import org.greenstone.gatherer.cdm.SearchType;
44import org.greenstone.gatherer.cdm.DOMProxyListModel;
45import org.greenstone.gatherer.gui.GComboBox;
46import org.greenstone.gatherer.gui.GLIButton;
47import org.greenstone.gatherer.util.Utility;
48import org.w3c.dom.*;
49
50/** This class maintains an ordered list of the search types available in the collection (MGPP command available in G2.39 or later). Currently only 'form' and 'plain' are valid.
51 * @author John Thompson, Greenstone Digital Library, University of Waikato
52 * @version 2.4
53 */
54public class SearchTypeManager
55 extends DOMProxyListModel {
56
57 static final public String[] SEARCH_TYPES = { "form", "plain" };
58
59 /** The controls used to edit the search types. */
60 private Control controls = null;
61 /** A reference to ourselves so our inner classes have access. */
62 private DOMProxyListModel model;
63
64 public SearchTypeManager(Element searchtypes_element) {
65 super(searchtypes_element, CollectionConfiguration.CONTENT_ELEMENT, new SearchType());
66 this.model = this;
67 Gatherer.println("SearchTypeManager: parsed " + getSize() + " search types.");
68 }
69
70 private void addSearchType(SearchType searchtype) {
71 if(!contains(searchtype)) {
72 add(getSize(), searchtype);
73 Gatherer.c_man.configurationChanged();
74 }
75 }
76
77 public Control getControls() {
78 if(controls == null) {
79 controls = new SearchTypeControl();
80 }
81 return controls;
82 }
83
84 /** Return a list of the currently assigned search types as a comma separated string.
85 * @return a String
86 */
87 public String getSearchTypes() {
88 StringBuffer search_types = new StringBuffer();
89 ArrayList types = children();
90 for (int i = 0; i < types.size(); i++) {
91 if (i>0) {
92 search_types.append(",");
93 }
94 search_types.append(((SearchType)types.get(i)).getName());
95 }
96 return search_types.toString();
97 }
98
99 /** Be examining the SearchType 'root' we were created with, determine if mgpp is enabled.
100 * @return true if MGPP is enabled, false otherwise
101 */
102 public boolean isMGPPEnabled() {
103 return root.getAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE).equals(CollectionConfiguration.TRUE_STR);
104 }
105
106 private void moveSearchType(SearchType search_type, boolean direction) {
107 // Try to move the classifier one step in the desired direction.
108 int index = indexOf(search_type);
109 if(direction) {
110 index--;
111 }
112 else {
113 index++;
114 }
115 // Check we aren't at an edge
116 if((direction && index < 0) || (!direction && index >= getSize())) {
117 String args[] = new String[2];
118 args[0] = Dictionary.get("CDM.SearchTypeManager.SearchType");
119 args[1] = search_type.toString();
120 String message = null;
121 if (direction) {
122 message = Dictionary.get("CDM.Move.At_Top", args);
123 }
124 else {
125 message = Dictionary.get("CDM.Move.At_Bottom", args);
126 }
127 JOptionPane.showMessageDialog(Gatherer.g_man, message, Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
128 return;
129 }
130 remove(search_type);
131 add(index, search_type);
132 Gatherer.c_man.configurationChanged();
133 }
134
135 private void removeSearchType(SearchType searchtype) {
136 if(contains(searchtype)) {
137 remove(searchtype);
138 Gatherer.c_man.configurationChanged();
139 }
140 }
141
142 private class SearchTypeControl
143 extends JPanel
144 implements Control {
145
146 private GComboBox search_type_combobox;
147
148 private JButton add_button;
149 private JButton move_down_button;
150 private JButton move_up_button;
151 private JButton remove_button;
152
153 private JCheckBox enable_advanced_searches_checkbox;
154
155 private JLabel current_search_types_label;
156 private JLabel search_type_label;
157 private JLabel title_label;
158
159 private JList current_search_types_list;
160
161 private JTextArea instructions_textarea;
162
163 public SearchTypeControl() {
164 // Creation
165 title_label = new JLabel();
166 title_label.setHorizontalAlignment(JLabel.CENTER);
167 Dictionary.registerText(title_label, "CDM.SearchTypeManager.Title");
168
169 JPanel instructions_panel = new JPanel();
170 instructions_textarea = new JTextArea();
171 instructions_textarea.setCaretPosition(0);
172 instructions_textarea.setEditable(false);
173 instructions_textarea.setLineWrap(true);
174 instructions_textarea.setRows(6);
175 instructions_textarea.setWrapStyleWord(true);
176 Dictionary.registerText(instructions_textarea, "CDM.SearchTypeManager.Instructions");
177
178 JPanel spacer_panel = new JPanel();
179
180 JPanel empty_panel = new JPanel();
181
182 JPanel inner_panel = new JPanel();
183
184 enable_advanced_searches_checkbox = new JCheckBox();
185 Dictionary.registerText(enable_advanced_searches_checkbox, "CDM.SearchTypeManager.Enable");
186
187 JPanel current_search_types_panel = new JPanel();
188 current_search_types_label = new JLabel();
189 Dictionary.registerText(current_search_types_label, "CDM.SearchTypeManager.Assigned");
190 current_search_types_list = new JList(model);
191 current_search_types_list.setVisibleRowCount(3);
192
193 JPanel movement_panel = new JPanel();
194
195 move_up_button = new JButton("", Utility.getImage("arrow-up.gif"));
196 move_up_button.setEnabled(false);
197 move_up_button.setMnemonic(KeyEvent.VK_U);
198 //move_up_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
199 Dictionary.registerBoth(move_up_button, "CDM.Move.Move_Up", "CDM.Move.Move_Up_Tooltip");
200
201 move_down_button = new JButton("", Utility.getImage("arrow-down.gif"));
202 move_down_button.setEnabled(false);
203 move_down_button.setMnemonic(KeyEvent.VK_D);
204 //move_down_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
205 Dictionary.registerBoth(move_down_button, "CDM.Move.Move_Down", "CDM.Move.Move_Down_Tooltip");
206
207 JPanel search_type_panel = new JPanel();
208 search_type_label = new JLabel();
209 Dictionary.registerText(search_type_label, "CDM.SearchTypeManager.SearchType_Selection");
210 search_type_combobox = new GComboBox(SEARCH_TYPES);
211 search_type_combobox.setPreferredSize(Utility.LABEL_SIZE);
212 search_type_combobox.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.editable_background", false));
213 search_type_combobox.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
214 search_type_combobox.setEditable(true);
215 search_type_combobox.setSelectedIndex(0);
216 search_type_combobox.setTextNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_foreground", false));
217 search_type_combobox.setTextSelectionColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
218 Dictionary.registerTooltip(search_type_combobox, "CDM.SearchTypeManager.SearchType_Selection_Tooltip");
219
220 JPanel button_panel = new JPanel();
221 add_button = new GLIButton();
222 add_button.setEnabled(false);
223 add_button.setMnemonic(KeyEvent.VK_A);
224 Dictionary.registerBoth(add_button, "CDM.SearchTypeManager.Add", "CDM.SearchTypeManager.Add_Tooltip");
225
226 remove_button = new GLIButton();
227 remove_button.setEnabled(false);
228 remove_button.setMnemonic(KeyEvent.VK_R);
229 Dictionary.registerBoth(remove_button, "CDM.SearchTypeManager.Remove", "CDM.SearchTypeManager.Remove_Tooltip");
230
231 // Connection
232 add_button.addActionListener(new AddActionListener());
233 current_search_types_list.addListSelectionListener(new CurrentSearchTypesListSelectionListener());
234 enable_advanced_searches_checkbox.addActionListener(new EnableAdvancedSearchesActionListener());
235 move_up_button.addActionListener(new MoveListener(true));
236 move_down_button.addActionListener(new MoveListener(false));
237 remove_button.addActionListener(new RemoveActionListener());
238 SearchTypesActionDocumentListener stadl = new SearchTypesActionDocumentListener();
239 search_type_combobox.addActionListener(stadl);
240 ((JTextField)search_type_combobox.getEditor().getEditorComponent()).getDocument().addDocumentListener(stadl);
241
242 // Layout
243 instructions_panel.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
244 instructions_panel.setLayout(new BorderLayout());
245 instructions_panel.add(title_label, BorderLayout.NORTH);
246 instructions_panel.add(new JScrollPane(instructions_textarea), BorderLayout.CENTER);
247
248 movement_panel.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
249 movement_panel.setLayout(new GridLayout(2,1,5,0));
250 movement_panel.add(move_up_button);
251 movement_panel.add(move_down_button);
252
253 current_search_types_panel.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
254 current_search_types_panel.setLayout(new BorderLayout());
255 current_search_types_panel.add(current_search_types_label, BorderLayout.NORTH);
256 current_search_types_panel.add(new JScrollPane(current_search_types_list), BorderLayout.CENTER);
257 current_search_types_panel.add(movement_panel, BorderLayout.EAST);
258
259 button_panel.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
260 button_panel.setLayout(new GridLayout(1,2,0,5));
261 button_panel.add(add_button);
262 button_panel.add(remove_button);
263
264 search_type_panel.setLayout(new BorderLayout(5,3));
265 search_type_panel.add(search_type_label, BorderLayout.WEST);
266 search_type_panel.add(search_type_combobox, BorderLayout.CENTER);
267 search_type_panel.add(button_panel, BorderLayout.SOUTH);
268
269 inner_panel.setLayout(new BorderLayout());
270 inner_panel.add(enable_advanced_searches_checkbox, BorderLayout.NORTH);
271 inner_panel.add(current_search_types_panel, BorderLayout.CENTER);
272 inner_panel.add(search_type_panel, BorderLayout.SOUTH);
273
274 spacer_panel.setLayout(new BorderLayout());
275 spacer_panel.add(inner_panel, BorderLayout.NORTH);
276 spacer_panel.add(empty_panel, BorderLayout.CENTER);
277
278 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
279 setLayout(new BorderLayout());
280 add(instructions_panel, BorderLayout.NORTH);
281 add(spacer_panel, BorderLayout.CENTER);
282 }
283
284 public void destroy() {
285 }
286
287 public void gainFocus() {
288 instructions_textarea.setCaretPosition(0);
289 validateControls(isMGPPEnabled());
290 }
291
292 public void loseFocus() {
293
294 }
295
296 private void validateControls(boolean advanced_search_enabled) {
297 // Enable or disable controls based on whether MGPP is enabled
298 // validate add button, which depends on the current combobox selection and the contents of the assigned search types list
299 Object selected_item = search_type_combobox.getSelectedItem();
300 add_button.setEnabled(advanced_search_enabled && selected_item != null && !model.contains(selected_item));
301 // validate other controls.
302 current_search_types_list.setEnabled(advanced_search_enabled);
303 enable_advanced_searches_checkbox.setSelected(advanced_search_enabled);
304 search_type_combobox.setEnabled(advanced_search_enabled);
305 remove_button.setEnabled(current_search_types_list.getModel().getSize() > 1 && !current_search_types_list.isSelectionEmpty() && advanced_search_enabled);
306 }
307
308 /** Listenes for actions on the Add button, and if detected adds a new search type. */
309 private class AddActionListener
310 implements ActionListener {
311 /** Called when someone actions the Add button.
312 * @param event an ActionEvent containing information about the add button click
313 */
314 public void actionPerformed(ActionEvent event) {
315 Object selected_item = search_type_combobox.getSelectedItem();
316 if(selected_item != null) {
317 if(search_type_combobox.getSelectedIndex() == -1) {
318 search_type_combobox.insertItemAt(selected_item, search_type_combobox.getItemCount());
319 }
320 // Add the search type
321 SearchType new_searchtype = new SearchType((String)selected_item);
322 addSearchType(new_searchtype);
323 }
324 add_button.setEnabled(false);
325 }
326 }
327
328 /** Listens for selections within the search types list and updates the remove button appropriately. */
329 private class CurrentSearchTypesListSelectionListener
330 implements ListSelectionListener {
331 /** Called when the selection in the list changes.
332 * @param event a ListSelectionEvent containing information about the selection change
333 */
334 public void valueChanged(ListSelectionEvent event) {
335 if(!event.getValueIsAdjusting()) {
336 SearchType search_type = null;
337 if ((search_type = (SearchType) current_search_types_list.getSelectedValue()) != null) {
338 int index = model.indexOf(search_type);
339 // Move up is only enabled if the current selection isn't at index 0
340 move_up_button.setEnabled(index != 0);
341 // Move down is only enabled if the current selection isn't at index getSize() - 1
342 move_down_button.setEnabled(index != model.getSize() - 1);
343 // Remove is only enabled if this isn't the last search type
344 remove_button.setEnabled(current_search_types_list.getModel().getSize() > 1);
345 }
346 else {
347 move_up_button.setEnabled(false);
348 move_down_button.setEnabled(false);
349 remove_button.setEnabled(false);
350 }
351 }
352 }
353 }
354
355 /** The most complex listener in this class, this listens for changes to the enable advanced searches checkbox, and when they occur it not only updates the controls on this page, but asks the IndexManager to action the appropriate changes to the underlying DOM so as to support either MG or MGPP styles of indexes. */
356 private class EnableAdvancedSearchesActionListener
357 implements ActionListener {
358 /** Called whenever the checkbox is checked or unchecked.
359 * @param event an ActionEvent containing information about the checking action
360 */
361 public void actionPerformed(ActionEvent event) {
362 Gatherer.g_man.wait(true);
363 boolean advanced_search_enabled = enable_advanced_searches_checkbox.isSelected();
364 model.root.setAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE, (advanced_search_enabled ? CollectionConfiguration.TRUE_STR : CollectionConfiguration.FALSE_STR));
365 CollectionDesignManager.index_manager.setMGPPEnabled(advanced_search_enabled);
366 validateControls(advanced_search_enabled);
367 Gatherer.g_man.wait(false);
368 }
369 }
370
371 /** Listenes for actions on the Remove button, and if detected removes the currently selected search types. */
372 private class RemoveActionListener
373 implements ActionListener {
374 /** Called when someone actions the Remove button.
375 * @param event an ActionEvent containing information about the remove button click
376 */
377 public void actionPerformed(ActionEvent event) {
378 if(!current_search_types_list.isSelectionEmpty()) {
379 Object[] selected_items = current_search_types_list.getSelectedValues();
380 for(int i = 0; model.getSize() > 1 && i < selected_items.length; i++) {
381 removeSearchType((SearchType)selected_items[i]);
382 }
383 }
384 Object selected_object = search_type_combobox.getSelectedItem();
385 if(selected_object != null) {
386 add_button.setEnabled(!model.contains(selected_object));
387 }
388 else {
389 add_button.setEnabled(false);
390 }
391 remove_button.setEnabled(false);
392 }
393 }
394
395 private class MoveListener
396 implements ActionListener {
397 private boolean move_up;
398 public MoveListener(boolean move_up) {
399 this.move_up = move_up;
400 }
401 public void actionPerformed(ActionEvent event) {
402 // Retrieve the first selected search type (if any)
403 SearchType search_type = null;
404 if((search_type = (SearchType) current_search_types_list.getSelectedValue()) != null) {
405 // Move search type
406 moveSearchType(search_type, move_up);
407 // Reselect the moved search type
408 current_search_types_list.setSelectedValue(search_type, true);
409 }
410 // No selection - no movement
411 else {
412 move_up_button.setEnabled(false);
413 move_down_button.setEnabled(false);
414 }
415 }
416 }
417
418 /** Listens for changes in the search types combobox, and enabled add button appropriately. */
419 private class SearchTypesActionDocumentListener
420 implements ActionListener, DocumentListener {
421 /** Called whenever a selection action occurs on the combobox.
422 * @param event an ActionEvent containing information about the selection event
423 */
424 public void actionPerformed(ActionEvent event) {
425 validateAddButton();
426 }
427
428 /** Gives notification that an attribute or set of attributes changed.
429 * @param event a DocumentEvent containing information about the text changed
430 */
431 public void changedUpdate(DocumentEvent event) {
432 validateAddButton();
433 }
434 /** Gives notification that there was an insert into the document.
435 * @param event a DocumentEvent containing information about the text added
436 */
437 public void insertUpdate(DocumentEvent event) {
438 validateAddButton();
439 }
440
441 /** Gives notification that a portion of the document has been removed.
442 * @param event a DocumentEvent containing information about the text removed
443 */
444 public void removeUpdate(DocumentEvent event) {
445 validateAddButton();
446 }
447
448 /** Change the enable state of the add button depending on the current value in the search type combobox. */
449 private void validateAddButton() {
450 Object selected_object = search_type_combobox.getSelectedItem();
451 if(selected_object != null) {
452 add_button.setEnabled(!model.contains(selected_object));
453 }
454 else {
455 add_button.setEnabled(false);
456 }
457 }
458 }
459 }
460}
Note: See TracBrowser for help on using the repository browser.