source: trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/SearchPanel.java@ 2281

Last change on this file since 2281 was 2281, checked in by daven, 23 years ago

turned on the BerryBasket. Try right-clicking on a result in the results List
to add one - no delete yet. Re-sizing maybe improved as well - no
guarantees yet though.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 18.8 KB
Line 
1/*
2 * SimpleGraphicalClient.java
3 * Copyright (C) 2001 New Zealand Digital Library Project
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.nzdl.gsdl.SimpleGraphicalClient;
20
21import java.awt.*;
22import java.awt.event.*;
23import java.io.*;
24import java.io.IOException;
25import java.util.*;
26import javax.swing.*;
27import javax.swing.event.*;
28import javax.swing.text.*;
29import javax.swing.text.html.*;
30
31
32// local libraries
33import org.nzdl.gsdl.service.NzdlCollectionInfo;
34import org.nzdl.gsdl.service.NzdlQuery;
35import org.nzdl.gsdl.service.NzdlRequest;
36import org.nzdl.gsdl.service.NzdlResponse;
37import org.nzdl.gsdl.service.NzdlResultSet;
38import org.nzdl.gsdl.service.NzdlService;
39import org.nzdl.gsdl.service.NzdlServiceClient;
40import org.nzdl.gsdl.util.*;
41
42
43/**
44 * A Class representing the Panel in which the Querying action happens.
45 *
46 * Does most of the actual `work' in the package.
47 *
48 * @author Dave Nichols ([email protected])
49 * @author stuart yeates ([email protected])
50 * @version $Revision: 2281 $
51 * @see org.nzdl.gsdl.service.SimpleGraphicalClient.SimpleGraphicalClient
52 * @see org.nzdl.gsdl.service.SimpleGraphicalClient.CSModel
53 * @see javax.swing.JPanel
54 */
55
56public class SearchPanel extends JPanel implements ActionListener, Constants
57{
58
59 CSModel csModel;
60 NzdlService nzdl;
61
62 JLabel collectionLabel;
63 JButton collectionInfoButton;
64 JTextField searchTextField;
65 JButton searchButton;
66 JComboBox collectionList;
67 JPanel queryFormulationPanel, resultsPanel, dataPanel, optionsPanel;
68 JPanel queryTypePanel, searchControlPanel;
69 JPanel collectionListPanel, searchTextFieldPanel, searchButtonPanel;
70 JPopupMenu resultPopup;
71 Result selectedResult;
72 ResultModel resultListModel;
73 JList resultsList;
74 JCheckBox stemCheckBox, caseFoldCheckBox;
75 JRadioButton rankedRadioButton, booleanRadioButton;
76 ButtonGroup buttonGroup;
77 JScrollPane scrollResultsPane;
78 JScrollPane scrollDataPane;
79 JFrame windowParent;
80 //JEditorPane documentPane;
81 JTextPane documentPane; // make this a JTextComponent ??
82 JTextArea documentArea;
83 JTextComponent documentComponent;
84 HTMLEditorKit htmlEditorKit = new HTMLEditorKit();
85 StyledEditorKit styledEditorKit = new StyledEditorKit();
86 GMLDocument htmlDoc = new GMLDocument();
87 DefaultStyledDocument defaultStyledDoc = new DefaultStyledDocument();
88 final static GMLDocument blankDoc = new GMLDocument();
89
90 /**
91 * Construct and initialise a new SearchPanel
92 */
93
94 public SearchPanel( CSModel newCsModel, JFrame parent)
95 {
96 super();
97 windowParent = parent;
98 csModel = newCsModel;
99 nzdl = csModel.getNzdlService();
100 setLayout( new BoxLayout(this, BoxLayout.Y_AXIS));
101 setBorder(BorderFactory.createTitledBorder("Search"));
102
103
104 searchTextField = new JTextField("Enter search terms here", 35) {
105 public boolean isRequestFocusEnabled(){
106 return true;
107 }
108 };
109 searchTextField.setText("Enter search terms here");
110 searchTextField.setFont(searchTextFieldFont);
111 searchTextField.setColumns(35);
112 searchTextField.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
113 searchButton = new JButton("Search");
114
115 searchButton.addActionListener(this);
116 //searchButton.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
117 searchButton.setPreferredSize(new Dimension(80, 20));
118
119 collectionListPanel = new JPanel();
120 collectionListPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
121 collectionListPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
122 collectionLabel = new JLabel("Collection: ");
123
124 collectionList = new JComboBox(csModel.getCollectionList()){
125 public boolean isFocusTraversable() {
126 return false;
127 }
128 };
129 collectionList.setEditable(false);
130
131 collectionInfoButton = new JButton("Info...") {
132 public String getToolTipText(MouseEvent e) {
133 return "Collection information for '" + csModel.getLongCollectionName((String)collectionList.getSelectedItem()) +"'";
134 }
135 };
136 ToolTipManager.sharedInstance().registerComponent(collectionInfoButton);
137 collectionInfoButton.addActionListener(this);
138
139 collectionListPanel.add(collectionLabel);
140 collectionListPanel.add(collectionList);
141 collectionListPanel.add(collectionInfoButton);
142
143 searchTextFieldPanel = new JPanel();
144 searchTextFieldPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
145 searchTextFieldPanel.add(searchTextField);
146
147 //NzdlPreferences prefs = NzdlPreferences.getInstance();
148 String queryType = NzdlConstants.DEFAULT_QUERY_TYPE;
149 if (NzdlPreferences.getInstance().isString(NzdlConstants.QUERYTYPE)) {
150 queryType = NzdlPreferences.getInstance().getString(NzdlConstants.QUERYTYPE);
151 }
152 // check integrity of queryType
153 if (!((queryType.equals(NzdlConstants.RANKED_STRING)) | (queryType.equals(NzdlConstants.BOOLEAN_STRING)))) {
154 // preferences may have been corrupted!
155 queryType = NzdlConstants.DEFAULT_QUERY_TYPE;
156 }
157 boolean stemming = NzdlConstants.DEFAULT_STEMMING;
158 if (NzdlPreferences.getInstance().isBoolean(NzdlConstants.STEMMING))
159 stemming = NzdlPreferences.getInstance().getBoolean(NzdlConstants.STEMMING);
160 boolean caseFolding = NzdlConstants.DEFAULT_CASE_FOLDING;
161 if (NzdlPreferences.getInstance().isBoolean(NzdlConstants.CASE_FOLDING))
162 caseFolding = NzdlPreferences.getInstance().getBoolean(NzdlConstants.CASE_FOLDING);
163
164 optionsPanel = new JPanel();
165
166 queryTypePanel = new JPanel();
167 queryTypePanel.setLayout(new GridLayout(2,1));
168 rankedRadioButton = new JRadioButton(NzdlConstants.RANKED_STRING);
169 rankedRadioButton.setActionCommand(NzdlConstants.RANKED_STRING);
170 rankedRadioButton.setSelected(queryType.equals(rankedRadioButton.getText()));
171 rankedRadioButton.setToolTipText("Display results in a ranked list");
172
173 booleanRadioButton = new JRadioButton(NzdlConstants.BOOLEAN_STRING);
174 booleanRadioButton.setActionCommand(NzdlConstants.BOOLEAN_STRING);
175 booleanRadioButton.setSelected(queryType.equals(booleanRadioButton.getText()));
176 booleanRadioButton.setToolTipText("Allows the use of Boolean operators: AND(&) OR(|) and NOT(!)");
177 buttonGroup = new ButtonGroup();
178 buttonGroup.add(rankedRadioButton);
179 buttonGroup.add(booleanRadioButton);
180 queryTypePanel.add(rankedRadioButton);
181 queryTypePanel.add(booleanRadioButton);
182
183 stemCheckBox = new JCheckBox("Stemming", stemming);
184 stemCheckBox.setToolTipText("Strip endings such as '...ing', '...ed'");
185 caseFoldCheckBox = new JCheckBox("Match case", caseFolding);
186 caseFoldCheckBox.setToolTipText("Only match when the case is the same");
187
188 optionsPanel.add(queryTypePanel);
189 optionsPanel.add(stemCheckBox);
190 optionsPanel.add(caseFoldCheckBox);
191
192 searchButtonPanel = new JPanel();
193 searchButtonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
194 searchButtonPanel.add(searchButton);
195
196 searchControlPanel = new JPanel();
197 searchControlPanel.setLayout(new BorderLayout());
198 searchControlPanel.add(optionsPanel, BorderLayout.WEST);
199 searchControlPanel.add(searchButtonPanel, BorderLayout.EAST);
200
201 queryFormulationPanel = new JPanel();
202 queryFormulationPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
203 queryFormulationPanel.setLayout(new BoxLayout(queryFormulationPanel, BoxLayout.Y_AXIS));
204 queryFormulationPanel.add(Box.createHorizontalStrut(100));
205 queryFormulationPanel.add(collectionListPanel);
206 queryFormulationPanel.add(searchTextFieldPanel);
207 queryFormulationPanel.add(searchControlPanel);
208
209 resultsPanel = new JPanel();
210 resultsPanel.setLayout(new BorderLayout());
211 resultsPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
212 resultListModel = csModel.getResultsModel();
213 resultsList = new JList(resultListModel);
214 resultsList.setFont(resultsFont);
215 resultsList.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
216 resultsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
217 scrollResultsPane = new JScrollPane(resultsList);
218 resultsPanel.add(scrollResultsPane, BorderLayout.CENTER);
219 csModel.addResult(Result.INITIAL_FAKE_RESULT);
220
221 resultPopup = new JPopupMenu();
222 JMenuItem addBerryItem = new JMenuItem("Add to BerryBasket");
223 addBerryItem.addActionListener(new ActionListener() {
224 public void actionPerformed(ActionEvent e) {
225 System.err.println("SelectedResult = " + selectedResult);
226 //System.err.println("add berry now...");
227 csModel.getBerryBasketModel().add( new Berry(selectedResult.getQueryHistoryItem(),selectedResult.getDocID(),selectedResult.getCollectionName(), selectedResult.toString()));
228 } // actionPerformed
229 });
230 resultPopup.add(addBerryItem);
231 MouseListener popupListener = new PopupListener();
232 resultsList.addMouseListener(popupListener);
233
234
235
236
237 dataPanel = new JPanel();
238 dataPanel.setLayout(new BorderLayout());
239 dataPanel.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
240 documentPane = new JTextPane() { // to control scrolling for raw text docs
241 public boolean getScrollableTracksViewportWidth() {
242 if (getSize().width < getParent().getSize().width)
243 return true;
244 else return false;
245 }
246 public void setSize(Dimension d) {
247 if (d.width < getParent().getSize().width)
248 d.width = getParent().getSize().width;
249 super.setSize(d);
250 }
251 }; // end custom JTextPane
252
253 documentPane.setEditable(false);
254 documentPane.setFont(docFont);
255 documentPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
256 //documentPane.setPreferredSize(new Dimension(100, 100));
257
258 scrollDataPane = new JScrollPane(documentPane);
259 scrollDataPane.setPreferredSize(new Dimension(300, 300));
260 dataPanel.add(scrollDataPane, BorderLayout.CENTER);
261
262 parent.getRootPane().setDefaultButton(searchButton);
263
264 resultsList.addListSelectionListener(new ResultListSelectionHandler() );
265
266 add(Box.createHorizontalStrut(400));
267 add(queryFormulationPanel);
268 add(resultsPanel);
269 add(dataPanel);
270 searchTextField.requestFocus();
271 }
272
273 /** respond to the user pressing the Search button */
274
275 public void actionPerformed(ActionEvent e) {
276 String collectionName = collectionList.getSelectedItem().toString();
277 if (e.getSource() == searchButton ) {
278 // cursor not set when RETURN pressed, only when button clicked ?
279 windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
280 String queryString = searchTextField.getText();
281 System.err.println("Search started (" + collectionName + "): \"" + queryString + "\" ..." );
282 //send query to collection
283 NzdlQuery nzdlQuery = new NzdlQuery(queryString);
284 nzdlQuery.setQueryType(buttonGroup.getSelection().getActionCommand());
285 //nzdlQuery.setQueryType("boolean");
286 nzdlQuery.setStemming(stemCheckBox.isSelected());
287 // interface reverses underlying logic so negate UI element state
288 nzdlQuery.setCaseFolding(! caseFoldCheckBox.isSelected());
289
290 // return the first numResults that match
291 nzdlQuery.setEndResults( -1 );
292 // "-1" means consider all the documents that match
293 nzdlQuery.setMaxDocs( -1 );
294
295 NzdlRequest request = new NzdlRequest( nzdlQuery );
296 NzdlResponse response = new NzdlResponse();
297
298 nzdl.service( collectionName, request, response );
299 NzdlResultSet results = response.getResultSet();
300 ArrayList docIDs = new ArrayList(results.getDocumentIDs());
301 // System.err.println("Size of docIDs = " + docIDs.size());
302 // paired collection of docIDs and Titles - but as Sets!
303 Map titleMetaData = nzdl.getMetaData( collectionName, docIDs, "Title" );
304 // created a paired collection of docIDs and Titles - as simple Strings!
305 HashMap titleMap = new HashMap();
306 for (ListIterator i = docIDs.listIterator(); i.hasNext(); ) {
307 String docID = (String) i.next();
308 //Set titleSet = (Set) titleMetaData.get( docID );
309 ArrayList titleList = new ArrayList((Set)titleMetaData.get(docID));
310 // use the first title as *the* title
311 titleMap.put(docID, titleList.get(0));
312 } // end for
313 // update the results list
314 csModel.clearResults();
315
316 QueryHistoryItem queryHistoryItem = new QueryHistoryItem(new Query(queryString), new Date(), collectionName, "user",docIDs.size(),buttonGroup.getSelection().getActionCommand(),stemCheckBox.isSelected(), caseFoldCheckBox.isSelected());
317 csModel.getQueryHistoryModel().add(queryHistoryItem);
318
319 if (docIDs.size() == 0 ) { // give some feedback for 0 results
320 csModel.addResult(Result.FAKE_RESULT);
321 documentPane.setStyledDocument(blankDoc);
322 }
323 else { // there are some results
324 Iterator docIDsIterator = docIDs.iterator();
325 while (docIDsIterator.hasNext()) {
326 String resultDocID = (String) docIDsIterator.next();
327 csModel.addResult(new Result((String)titleMap.get(resultDocID), resultDocID, collectionName, queryHistoryItem ));
328 } //end while
329 if (NzdlPreferences.getInstance().getBoolean(NzdlConstants.DISPLAY_FIRST_DOC))
330 resultsList.setSelectedIndex(0);
331 } // end else
332
333 /*
334 csModel.getQueryHistoryModel().add( new QueryHistoryItem(new Query(queryString), new Date(), collectionName, "user",docIDs.size(),buttonGroup.getSelection().getActionCommand(),stemCheckBox.isSelected(), caseFoldCheckBox.isSelected() ));
335 */
336 titleMap.clear();
337 titleMetaData.clear();
338 docIDs.clear();
339 windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
340 } // end if
341 else {
342 if (e.getSource() == collectionInfoButton) {
343 CollectionInfoDialog cid = new CollectionInfoDialog(windowParent, collectionName, csModel);
344 }
345 else {
346 System.err.println("unknown Action event in SearchPanel");
347 }
348 }
349 } //end actionPerformed
350
351 /** handles selection events in the results list so that when the
352 user selects a new title (say) the document contents is
353 automatically displayed in the main panel */
354
355 class ResultListSelectionHandler implements ListSelectionListener {
356
357 // private Result previousSelection = null;
358
359 public void valueChanged(ListSelectionEvent e) {
360 // get the result object from the SelectedIndex
361 // assume we only get here with events from resultsList
362 int docLength = 0;
363 if (e.getValueIsAdjusting()) { return; }
364 Result result = (Result) resultsList.getSelectedValue();
365 if ((result == Result.FAKE_RESULT) || (result == Result.INITIAL_FAKE_RESULT)) {
366 documentPane.setStyledDocument( blankDoc );
367 System.err.println("clicked on fake result");
368 }
369 else { // a real result representing a real document to deal with
370
371 windowParent.setCursor(WAIT_CURSOR);
372
373 deleteDocContents(); // for memory/garbage collection
374
375 StringReader sr = new StringReader(nzdl.getDocument(result.getCollectionName(), result.getDocID()));
376
377 if (NzdlPreferences.getInstance().getBoolean(NzdlConstants.RAW_TEXT))
378 // display the document as raw text
379 displayAsRawText(sr);
380 else {
381 // treat as HTML
382 displayAsHTML(sr);
383 //htmlDoc.getImageData(nzdl, result.getCollectionName());
384 }
385
386 windowParent.setCursor(NORMAL_CURSOR);
387 }
388 } //end valueChanged
389 }//end ResultListSelectionHandler
390
391
392
393 private void deleteDocContents() {
394 //trash the old htmlDoc for memory/garbage collection
395 try {
396 if (htmlDoc != null)
397 htmlDoc.remove(0, htmlDoc.getLength());
398 if (defaultStyledDoc != null)
399 defaultStyledDoc.remove(0, defaultStyledDoc.getLength());
400 }
401 catch (Exception exception) {
402 throw new Error (exception.toString());
403 }
404 } // end deleteDocContents
405
406
407 public void switchToRawText() {
408 windowParent.setCursor(WAIT_CURSOR);
409 System.err.println("switching to raw text");
410 displayAsRawText(new StringReader(documentPane.getText()));
411 windowParent.setCursor(NORMAL_CURSOR);
412 }
413
414 public void displayAsRawText(StringReader sr) {
415 defaultStyledDoc = new DefaultStyledDocument();
416 documentPane.setEditorKit(styledEditorKit);
417 try {
418 styledEditorKit.read( sr, defaultStyledDoc, 0);
419 }
420 catch (Exception e) {
421 System.err.println(e);
422 }
423 documentPane.setDocument(defaultStyledDoc);
424 setCaretToStart(defaultStyledDoc.getLength());
425 } // end displayAsRawText
426
427
428 public void switchToHTML() {
429 windowParent.setCursor(WAIT_CURSOR);
430 System.err.println("switching to HTML");
431 displayAsHTML(new StringReader(documentPane.getText()));
432 windowParent.setCursor(NORMAL_CURSOR);
433 }
434
435 public void displayAsHTML(StringReader sr) {
436 htmlDoc = new GMLDocument();
437 documentPane.setEditorKit(htmlEditorKit);
438 try {
439 htmlEditorKit.read( sr, htmlDoc, 0);
440 }
441 catch (Exception e) {
442 System.err.println(e);
443 }
444 documentPane.setStyledDocument( htmlDoc );
445 setCaretToStart(htmlDoc.getLength());
446 } // end displayAsHTML
447
448
449 private void setCaretToStart(int docLength) {
450 // it seems as if they haven't considered
451 // documents with > MAX_INT num of chars ...
452 if (docLength > 0)
453 documentPane.setCaretPosition(1);
454 }
455
456 /*
457 * save prefs not in preferencesDialog
458 */
459 public void savePrefs() {
460 NzdlPreferences.getInstance().setBoolean(NzdlConstants.STEMMING,stemCheckBox.isSelected());
461 NzdlPreferences.getInstance().setBoolean(NzdlConstants.CASE_FOLDING,caseFoldCheckBox.isSelected());
462 NzdlPreferences.getInstance().setString(NzdlConstants.QUERYTYPE,buttonGroup.getSelection().getActionCommand());
463 } //savePrefs
464
465
466 class PopupListener extends MouseAdapter {
467 public void mousePressed(MouseEvent e) {
468 maybeShowPopup(e);
469 }
470
471 public void mouseReleased(MouseEvent e) {
472 maybeShowPopup(e);
473 }
474
475 private void maybeShowPopup(MouseEvent e) {
476 if (e.isPopupTrigger()) {
477 int index = resultsList.locationToIndex(new Point(e.getX(), e.getY()));
478 if (index < resultListModel.getSize()) {
479 Result result = (Result) resultListModel.getElementAt(index);
480 if (result != Result.INITIAL_FAKE_RESULT) {
481 selectedResult = result;
482 resultPopup.show(e.getComponent(),
483 e.getX(), e.getY());
484 }
485 }
486 else
487 System.err.println("popup not on item");
488 }
489 }
490 } // PopupListener
491
492
493
494} //end SearchPanel
Note: See TracBrowser for help on using the repository browser.