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

Last change on this file since 11038 was 11038, checked in by mdewsnip, 18 years ago

Tidied up the look of the Design pane. Each Design pane screen now has consistent borders, and vertical spacing between elements has been improved.

  • Property svn:keywords set to Author Date Id Revision
File size: 21.4 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.Configuration;
35import org.greenstone.gatherer.DebugStream;
36import org.greenstone.gatherer.Dictionary;
37import org.greenstone.gatherer.Gatherer;
38import org.greenstone.gatherer.gui.DesignPaneHeader;
39import org.greenstone.gatherer.gui.GComboBox;
40import org.greenstone.gatherer.gui.GLIButton;
41import org.greenstone.gatherer.util.JarTools;
42import org.w3c.dom.*;
43
44/** This class maintains an ordered list of the search types available in the collection (MGPP/lucene command available in G2.39 or later). Currently only 'form' and 'plain' are valid.
45 * @author John Thompson, Greenstone Digital Library, University of Waikato
46 * @version 2.4
47 */
48public class SearchTypeManager
49 extends DOMProxyListModel
50{
51 static final private Dimension LABEL_SIZE = new Dimension(150, 25);
52
53 static final public String BUILD_TYPE_LUCENE = "lucene";
54 static final public String BUILD_TYPE_MGPP = "mgpp";
55
56 static final public String[] SEARCH_TYPES = { "plain" , "form"};
57 static final public String[] BUILD_TYPES = { BUILD_TYPE_LUCENE, BUILD_TYPE_MGPP };
58
59 /** the buildtype element in the config file - searchtypemanager looks
60 * after this now */
61 public CollectionMeta build_type = null;
62 /** The controls used to edit the search types. */
63 private Control controls = null;
64 /** A reference to ourselves so our inner classes have access. */
65 private DOMProxyListModel model;
66
67 public SearchTypeManager(Element searchtypes_element) {
68 super(searchtypes_element, CollectionConfiguration.CONTENT_ELEMENT, new SearchType());
69 this.model = this;
70 DebugStream.println("SearchTypeManager: parsed " + getSize() + " search types.");
71 build_type = new CollectionMeta(CollectionDesignManager.collect_config.getBuildType());
72
73 }
74
75 private void addSearchType(SearchType searchtype) {
76 if(!contains(searchtype)) {
77 add(getSize(), searchtype);
78 Gatherer.c_man.configurationChanged();
79 }
80 }
81
82 public Control getControls() {
83 if(controls == null) {
84 controls = new SearchTypeControl();
85 }
86 return controls;
87 }
88
89 /** Return a list of the currently assigned search types as a comma separated string.
90 * @return a String
91 */
92 public String getSearchTypes() {
93 StringBuffer search_types = new StringBuffer();
94 ArrayList types = children();
95 for (int i = 0; i < types.size(); i++) {
96 if (i>0) {
97 search_types.append(",");
98 }
99 search_types.append(((SearchType)types.get(i)).getName());
100 }
101 return search_types.toString();
102 }
103
104 /** By examining the SearchType 'root' we were created with, determine if mgpp is enabled.
105 * @return true if MGPP is enabled, false otherwise
106 */
107 public boolean isSearchTypeEnabled() {
108 return root.getAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE).equals(CollectionConfiguration.TRUE_STR);
109 }
110
111 public boolean isMGPP() {
112 return isSearchTypeEnabled() && build_type.getValue(CollectionMeta.TEXT).equals(BUILD_TYPE_MGPP);
113 }
114
115 public boolean isLucene() {
116 return isSearchTypeEnabled() && build_type.getValue(CollectionMeta.TEXT).equals(BUILD_TYPE_LUCENE);
117 }
118
119 private void moveSearchType(SearchType search_type, boolean direction) {
120 // Try to move the classifier one step in the desired direction.
121 int index = indexOf(search_type);
122 if(direction) {
123 index--;
124 }
125 else {
126 index++;
127 }
128 // Check we aren't at an edge
129 if((direction && index < 0) || (!direction && index >= getSize())) {
130 String args[] = new String[2];
131 args[0] = Dictionary.get("CDM.SearchTypeManager.SearchType");
132 args[1] = search_type.toString();
133 String message = null;
134 if (direction) {
135 message = Dictionary.get("CDM.Move.At_Top", args);
136 }
137 else {
138 message = Dictionary.get("CDM.Move.At_Bottom", args);
139 }
140 JOptionPane.showMessageDialog(Gatherer.g_man, message, Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
141 return;
142 }
143 remove(search_type);
144 add(index, search_type);
145 Gatherer.c_man.configurationChanged();
146 }
147
148 private void removeSearchType(SearchType searchtype) {
149 if(contains(searchtype)) {
150 remove(searchtype);
151 Gatherer.c_man.configurationChanged();
152 }
153 }
154
155 private class SearchTypeControl
156 extends JPanel
157 implements Control {
158
159 private GComboBox search_type_combobox;
160 private GComboBox build_type_combobox;
161
162 private JButton add_button;
163 private JButton move_down_button;
164 private JButton move_up_button;
165 private JButton remove_button;
166
167 private JCheckBox enable_advanced_searches_checkbox;
168
169 private JLabel current_search_types_label;
170 private JLabel search_type_label;
171 private JList current_search_types_list;
172
173 public SearchTypeControl() {
174
175 // Creation
176 JPanel header_panel = new DesignPaneHeader("CDM.GUI.SearchTypes", "searchtypes");
177
178 JPanel spacer_panel = new JPanel();
179
180 JPanel empty_panel = new JPanel();
181
182 JPanel inner_panel = new JPanel();
183
184 JPanel indexer_type_panel = new JPanel();
185 JPanel build_type_panel = new JPanel();
186
187 enable_advanced_searches_checkbox = new JCheckBox();
188 Dictionary.registerText(enable_advanced_searches_checkbox, "CDM.SearchTypeManager.Enable");
189
190 build_type_combobox = new GComboBox(BUILD_TYPES);
191 build_type_combobox.setPreferredSize(LABEL_SIZE);
192 build_type_combobox.setBackgroundNonSelectionColor(Configuration.getColor("coloring.editable_background", false));
193 build_type_combobox.setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false));
194 build_type_combobox.setEditable(true);
195 build_type_combobox.setSelectedIndex(1);// mgpp is at 1
196 String selected_value = build_type.getValue(CollectionMeta.TEXT);
197 if (!selected_value.equals("")) {
198 for (int i=0; i<build_type_combobox.getItemCount();i++) {
199 String item = (String)build_type_combobox.getItemAt(i);
200 if (item.equals(selected_value)) {
201 build_type_combobox.setSelectedIndex(i);
202 break;
203 }
204 }
205 } else {
206 //build_type.setValue((String)build_type_combobox.getSelectedItem());
207 build_type.setAssigned(isSearchTypeEnabled());
208
209 }
210 build_type_combobox.setTextNonSelectionColor(Configuration.getColor("coloring.workspace_tree_foreground", false));
211 build_type_combobox.setTextSelectionColor(Configuration.getColor("coloring.collection_selection_foreground", false));
212 Dictionary.registerTooltip(build_type_combobox, "CDM.SearchTypeManager.BuildType_Selection_Tooltip");
213
214 JLabel build_type_label = new JLabel();
215 Dictionary.registerText(build_type_label, "CDM.SearchTypeManager.BuildType_Selection");
216 JPanel current_search_types_panel = new JPanel();
217 current_search_types_label = new JLabel();
218 Dictionary.registerText(current_search_types_label, "CDM.SearchTypeManager.Assigned");
219 current_search_types_list = new JList(model);
220 current_search_types_list.setVisibleRowCount(3);
221
222 JPanel movement_panel = new JPanel();
223
224 move_up_button = new JButton("", JarTools.getImage("arrow-up.gif"));
225 move_up_button.setEnabled(false);
226 move_up_button.setMnemonic(KeyEvent.VK_U);
227
228 Dictionary.registerBoth(move_up_button, "CDM.Move.Move_Up", "CDM.Move.Move_Up_Tooltip");
229
230 move_down_button = new JButton("", JarTools.getImage("arrow-down.gif"));
231 move_down_button.setEnabled(false);
232 move_down_button.setMnemonic(KeyEvent.VK_D);
233
234 Dictionary.registerBoth(move_down_button, "CDM.Move.Move_Down", "CDM.Move.Move_Down_Tooltip");
235
236 JPanel search_type_panel = new JPanel();
237 search_type_label = new JLabel();
238 Dictionary.registerText(search_type_label, "CDM.SearchTypeManager.SearchType_Selection");
239 search_type_combobox = new GComboBox(SEARCH_TYPES);
240 search_type_combobox.setPreferredSize(LABEL_SIZE);
241 search_type_combobox.setBackgroundNonSelectionColor(Configuration.getColor("coloring.editable_background", false));
242 search_type_combobox.setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false));
243 search_type_combobox.setEditable(true);
244 search_type_combobox.setSelectedIndex(0);
245 search_type_combobox.setTextNonSelectionColor(Configuration.getColor("coloring.workspace_tree_foreground", false));
246 search_type_combobox.setTextSelectionColor(Configuration.getColor("coloring.collection_selection_foreground", false));
247 Dictionary.registerTooltip(search_type_combobox, "CDM.SearchTypeManager.SearchType_Selection_Tooltip");
248
249 JPanel button_panel = new JPanel();
250 add_button = new GLIButton();
251 add_button.setEnabled(false);
252 add_button.setMnemonic(KeyEvent.VK_A);
253 Dictionary.registerBoth(add_button, "CDM.SearchTypeManager.Add", "CDM.SearchTypeManager.Add_Tooltip");
254
255 remove_button = new GLIButton();
256 remove_button.setEnabled(false);
257 remove_button.setMnemonic(KeyEvent.VK_R);
258 Dictionary.registerBoth(remove_button, "CDM.SearchTypeManager.Remove", "CDM.SearchTypeManager.Remove_Tooltip");
259
260
261 // Connection
262 add_button.addActionListener(new AddActionListener());
263 add_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
264 build_type_combobox.addActionListener(new BuildTypeActionListener());
265 build_type_combobox.addActionListener(CollectionDesignManager.buildcol_change_listener);
266 current_search_types_list.addListSelectionListener(new CurrentSearchTypesListSelectionListener());
267 enable_advanced_searches_checkbox.addActionListener(new EnableAdvancedSearchesActionListener());
268 enable_advanced_searches_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
269 move_up_button.addActionListener(new MoveListener(true));
270 move_up_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
271 move_down_button.addActionListener(new MoveListener(false));
272 move_down_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
273 remove_button.addActionListener(new RemoveActionListener());
274 remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
275 SearchTypesActionDocumentListener stadl = new SearchTypesActionDocumentListener();
276 search_type_combobox.addActionListener(stadl);
277 search_type_combobox.addActionListener(CollectionDesignManager.buildcol_change_listener);
278 ((JTextField)search_type_combobox.getEditor().getEditorComponent()).getDocument().addDocumentListener(stadl);
279
280 // Layout
281 movement_panel.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
282 movement_panel.setLayout(new GridLayout(2,1,5,0));
283 movement_panel.add(move_up_button);
284 movement_panel.add(move_down_button);
285
286 current_search_types_panel.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
287 current_search_types_panel.setLayout(new BorderLayout());
288 current_search_types_panel.add(current_search_types_label, BorderLayout.NORTH);
289 current_search_types_panel.add(new JScrollPane(current_search_types_list), BorderLayout.CENTER);
290 current_search_types_panel.add(movement_panel, BorderLayout.EAST);
291
292 build_type_panel.setLayout(new BorderLayout());
293 build_type_panel.add(build_type_label, BorderLayout.WEST);
294 build_type_panel.add(build_type_combobox, BorderLayout.CENTER);
295
296 indexer_type_panel.setLayout(new GridLayout(1,2,0,5));
297 indexer_type_panel.add(enable_advanced_searches_checkbox);
298 indexer_type_panel.add(build_type_panel);
299
300 button_panel.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
301 button_panel.setLayout(new GridLayout(1,2,0,5));
302 button_panel.add(add_button);
303 button_panel.add(remove_button);
304
305 search_type_panel.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
306 search_type_panel.setLayout(new BorderLayout(5,3));
307 search_type_panel.add(search_type_label, BorderLayout.WEST);
308 search_type_panel.add(search_type_combobox, BorderLayout.CENTER);
309 search_type_panel.add(button_panel, BorderLayout.SOUTH);
310
311 inner_panel.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
312 inner_panel.setLayout(new BorderLayout());
313 inner_panel.add(indexer_type_panel, BorderLayout.NORTH);
314 inner_panel.add(current_search_types_panel, BorderLayout.CENTER);
315 inner_panel.add(search_type_panel, BorderLayout.SOUTH);
316
317 spacer_panel.setLayout(new BorderLayout());
318 spacer_panel.add(inner_panel, BorderLayout.NORTH);
319 spacer_panel.add(empty_panel, BorderLayout.CENTER);
320
321 setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
322 setLayout(new BorderLayout());
323 add(header_panel, BorderLayout.NORTH);
324 add(spacer_panel, BorderLayout.CENTER);
325 }
326
327 public void destroy() {
328 }
329
330 public void gainFocus() {
331 validateControls(isSearchTypeEnabled());
332 }
333
334 public void loseFocus() {
335
336 }
337
338 private void validateControls(boolean advanced_search_enabled) {
339 // Enable or disable controls based on whether MGPP is enabled
340 // validate add button, which depends on the current combobox selection and the contents of the assigned search types list
341 Object selected_item = search_type_combobox.getSelectedItem();
342 add_button.setEnabled(advanced_search_enabled && selected_item != null && !model.contains(selected_item));
343 // validate other controls.
344 current_search_types_list.setEnabled(advanced_search_enabled);
345 build_type_combobox.setEnabled(advanced_search_enabled);
346 enable_advanced_searches_checkbox.setSelected(advanced_search_enabled);
347 search_type_combobox.setEnabled(advanced_search_enabled);
348 remove_button.setEnabled(current_search_types_list.getModel().getSize() > 1 && !current_search_types_list.isSelectionEmpty() && advanced_search_enabled);
349 }
350
351 /** Listenes for actions on the Add button, and if detected adds a new search type. */
352 private class AddActionListener
353 implements ActionListener {
354 /** Called when someone actions the Add button.
355 * @param event an ActionEvent containing information about the add button click
356 */
357 public void actionPerformed(ActionEvent event) {
358 Object selected_item = search_type_combobox.getSelectedItem();
359 if(selected_item != null) {
360 if(search_type_combobox.getSelectedIndex() == -1) {
361 search_type_combobox.insertItemAt(selected_item, search_type_combobox.getItemCount());
362 }
363 // Add the search type
364 SearchType new_searchtype = new SearchType((String)selected_item);
365 addSearchType(new_searchtype);
366 }
367 add_button.setEnabled(false);
368 }
369 }
370
371 /** Listens for selections within the search types list and updates the remove button appropriately. */
372 private class CurrentSearchTypesListSelectionListener
373 implements ListSelectionListener {
374 /** Called when the selection in the list changes.
375 * @param event a ListSelectionEvent containing information about the selection change
376 */
377 public void valueChanged(ListSelectionEvent event) {
378 if(!event.getValueIsAdjusting()) {
379 SearchType search_type = null;
380 if ((search_type = (SearchType) current_search_types_list.getSelectedValue()) != null) {
381 int index = model.indexOf(search_type);
382 // Move up is only enabled if the current selection isn't at index 0
383 move_up_button.setEnabled(index != 0);
384 // Move down is only enabled if the current selection isn't at index getSize() - 1
385 move_down_button.setEnabled(index != model.getSize() - 1);
386 // Remove is only enabled if this isn't the last search type
387 remove_button.setEnabled(current_search_types_list.getModel().getSize() > 1);
388 }
389 else {
390 move_up_button.setEnabled(false);
391 move_down_button.setEnabled(false);
392 remove_button.setEnabled(false);
393 }
394 }
395 }
396 }
397
398 /** 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. */
399 private class EnableAdvancedSearchesActionListener
400 implements ActionListener {
401 /** Called whenever the checkbox is checked or unchecked.
402 * @param event an ActionEvent containing information about the checking action
403 */
404 public void actionPerformed(ActionEvent event) {
405 Gatherer.g_man.wait(true);
406 boolean advanced_search_enabled = enable_advanced_searches_checkbox.isSelected();
407
408 model.root.setAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE, (advanced_search_enabled ? CollectionConfiguration.TRUE_STR : CollectionConfiguration.FALSE_STR));
409 validateControls(advanced_search_enabled);
410 if ((!build_type.isAssigned() && advanced_search_enabled) ||
411 (build_type.isAssigned() && !advanced_search_enabled)) {
412
413 build_type.setAssigned(advanced_search_enabled);
414 Gatherer.c_man.configurationChanged();
415 }
416 if (build_type.isAssigned() && build_type.getValue(true).equals("")) {
417 build_type.setValue((String)build_type_combobox.getSelectedItem());
418 }
419 Gatherer.g_man.wait(false);
420 }
421 }
422
423 private class BuildTypeActionListener
424 implements ActionListener {
425
426 public void actionPerformed(ActionEvent event) {
427 if (!build_type.getValue(CollectionMeta.TEXT).equals((String)build_type_combobox.getSelectedItem())) {
428 build_type.setValue((String)build_type_combobox.getSelectedItem());
429 }
430 }
431
432 }
433 /** Listenes for actions on the Remove button, and if detected removes the currently selected search types. */
434 private class RemoveActionListener
435 implements ActionListener {
436 /** Called when someone actions the Remove button.
437 * @param event an ActionEvent containing information about the remove button click
438 */
439 public void actionPerformed(ActionEvent event) {
440 if(!current_search_types_list.isSelectionEmpty()) {
441 Object[] selected_items = current_search_types_list.getSelectedValues();
442 for(int i = 0; model.getSize() > 1 && i < selected_items.length; i++) {
443 removeSearchType((SearchType)selected_items[i]);
444 }
445 }
446 Object selected_object = search_type_combobox.getSelectedItem();
447 if(selected_object != null) {
448 add_button.setEnabled(!model.contains(selected_object));
449 }
450 else {
451 add_button.setEnabled(false);
452 }
453 remove_button.setEnabled(false);
454 }
455 }
456
457 private class MoveListener
458 implements ActionListener {
459 private boolean move_up;
460 public MoveListener(boolean move_up) {
461 this.move_up = move_up;
462 }
463 public void actionPerformed(ActionEvent event) {
464 // Retrieve the first selected search type (if any)
465 SearchType search_type = null;
466 if((search_type = (SearchType) current_search_types_list.getSelectedValue()) != null) {
467 // Move search type
468 moveSearchType(search_type, move_up);
469 // Reselect the moved search type
470 current_search_types_list.setSelectedValue(search_type, true);
471 }
472 // No selection - no movement
473 else {
474 move_up_button.setEnabled(false);
475 move_down_button.setEnabled(false);
476 }
477 }
478 }
479
480 /** Listens for changes in the search types combobox, and enabled add button appropriately. */
481 private class SearchTypesActionDocumentListener
482 implements ActionListener, DocumentListener {
483 /** Called whenever a selection action occurs on the combobox.
484 * @param event an ActionEvent containing information about the selection event
485 */
486 public void actionPerformed(ActionEvent event) {
487 validateAddButton();
488 }
489
490 /** Gives notification that an attribute or set of attributes changed.
491 * @param event a DocumentEvent containing information about the text changed
492 */
493 public void changedUpdate(DocumentEvent event) {
494 validateAddButton();
495 }
496 /** Gives notification that there was an insert into the document.
497 * @param event a DocumentEvent containing information about the text added
498 */
499 public void insertUpdate(DocumentEvent event) {
500 validateAddButton();
501 }
502
503 /** Gives notification that a portion of the document has been removed.
504 * @param event a DocumentEvent containing information about the text removed
505 */
506 public void removeUpdate(DocumentEvent event) {
507 validateAddButton();
508 }
509
510 /** Change the enable state of the add button depending on the current value in the search type combobox. */
511 private void validateAddButton() {
512 Object selected_object = search_type_combobox.getSelectedItem();
513 if(selected_object != null) {
514 add_button.setEnabled(!model.contains(selected_object));
515 }
516 else {
517 add_button.setEnabled(false);
518 }
519 }
520 }
521 }
522}
Note: See TracBrowser for help on using the repository browser.