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

Last change on this file since 5234 was 5234, checked in by jmt12, 21 years ago

Move buttons now actually do something ;)

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