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

Last change on this file since 6540 was 6318, checked in by jmt12, 20 years ago

Changed JButtons for GLIButtons, which know whether they should paint their background depending on what platform they are run on, and finished keyboard shortcuts

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