[2143] | 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 | */
|
---|
[2142] | 19 | package org.nzdl.gsdl.SimpleGraphicalClient;
|
---|
| 20 |
|
---|
| 21 | import java.awt.*;
|
---|
| 22 | import java.awt.event.*;
|
---|
[2165] | 23 | import java.io.*;
|
---|
[2159] | 24 | import java.io.IOException;
|
---|
[2142] | 25 | import java.util.*;
|
---|
[2148] | 26 | import javax.swing.*;
|
---|
[2153] | 27 | import javax.swing.event.*;
|
---|
| 28 | import javax.swing.text.*;
|
---|
| 29 | import javax.swing.text.html.*;
|
---|
[2142] | 30 |
|
---|
[2153] | 31 |
|
---|
[2142] | 32 | // local libraries
|
---|
| 33 | import org.nzdl.gsdl.service.NzdlCollectionInfo;
|
---|
| 34 | import org.nzdl.gsdl.service.NzdlQuery;
|
---|
| 35 | import org.nzdl.gsdl.service.NzdlRequest;
|
---|
| 36 | import org.nzdl.gsdl.service.NzdlResponse;
|
---|
| 37 | import org.nzdl.gsdl.service.NzdlResultSet;
|
---|
| 38 | import org.nzdl.gsdl.service.NzdlService;
|
---|
| 39 | import org.nzdl.gsdl.service.NzdlServiceClient;
|
---|
[2190] | 40 | import org.nzdl.gsdl.util.NzdlPreferences;
|
---|
[2142] | 41 |
|
---|
| 42 |
|
---|
[2143] | 43 | /**
|
---|
[2153] | 44 | * A Class representing the Panel in which the Querying action happens.
|
---|
[2143] | 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: 2225 $
|
---|
[2159] | 51 | * @see org.nzdl.gsdl.service.SimpleGraphicalClient.SimpleGraphicalClient
|
---|
| 52 | * @see org.nzdl.gsdl.service.SimpleGraphicalClient.CSModel
|
---|
[2143] | 53 | * @see javax.swing.JPanel
|
---|
| 54 | */
|
---|
[2142] | 55 |
|
---|
| 56 | public class SearchPanel extends JPanel implements ActionListener, Constants
|
---|
| 57 | {
|
---|
| 58 |
|
---|
[2143] | 59 | CSModel csModel;
|
---|
[2154] | 60 | NzdlService nzdl;
|
---|
| 61 |
|
---|
[2143] | 62 | JLabel collectionLabel;
|
---|
[2195] | 63 | JButton collectionInfoButton;
|
---|
[2143] | 64 | JTextField searchTextField;
|
---|
| 65 | JButton searchButton;
|
---|
[2154] | 66 | JComboBox collectionList;
|
---|
[2143] | 67 | JPanel queryFormulationPanel, resultsPanel, dataPanel;
|
---|
| 68 | JPanel collectionListPanel, searchTextFieldPanel, searchButtonPanel;
|
---|
| 69 | JList resultsList;
|
---|
| 70 | JScrollPane scrollResultsPane;
|
---|
[2153] | 71 | JScrollPane scrollDataPane;
|
---|
| 72 | JFrame windowParent;
|
---|
[2165] | 73 | //JEditorPane documentPane;
|
---|
[2190] | 74 | JTextPane documentPane; // make this a JTextComponent ??
|
---|
| 75 | JTextArea documentArea;
|
---|
| 76 | JTextComponent documentComponent;
|
---|
| 77 | HTMLEditorKit htmlEditorKit = new HTMLEditorKit();
|
---|
| 78 | StyledEditorKit styledEditorKit = new StyledEditorKit();
|
---|
[2165] | 79 | GMLDocument htmlDoc = new GMLDocument();
|
---|
[2190] | 80 | DefaultStyledDocument defaultStyledDoc = new DefaultStyledDocument();
|
---|
[2165] | 81 | final static GMLDocument blankDoc = new GMLDocument();
|
---|
[2153] | 82 |
|
---|
[2167] | 83 | /**
|
---|
[2143] | 84 | * Construct and initialise a new SearchPanel
|
---|
| 85 | */
|
---|
| 86 |
|
---|
[2142] | 87 | public SearchPanel( CSModel newCsModel, JFrame parent)
|
---|
| 88 | {
|
---|
| 89 | super();
|
---|
[2153] | 90 | windowParent = parent;
|
---|
[2143] | 91 | csModel = newCsModel;
|
---|
[2154] | 92 | nzdl = csModel.getNzdlService();
|
---|
[2142] | 93 | setLayout( new BoxLayout(this, BoxLayout.Y_AXIS));
|
---|
[2143] | 94 | setBorder(BorderFactory.createTitledBorder("Search"));
|
---|
[2142] | 95 |
|
---|
| 96 |
|
---|
[2143] | 97 | searchTextField = new JTextField("Enter search terms here", 35) {
|
---|
| 98 | public boolean isRequestFocusEnabled(){
|
---|
| 99 | return true;
|
---|
| 100 | }
|
---|
| 101 | };
|
---|
| 102 | searchTextField.setText("Enter search terms here");
|
---|
| 103 | searchTextField.setFont(searchTextFieldFont);
|
---|
| 104 | searchTextField.setColumns(35);
|
---|
[2177] | 105 | searchTextField.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
[2143] | 106 | searchButton = new JButton("Search");
|
---|
[2142] | 107 |
|
---|
[2143] | 108 | searchButton.addActionListener(this);
|
---|
| 109 | //searchButton.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
|
---|
| 110 | searchButton.setPreferredSize(new Dimension(80, 20));
|
---|
[2142] | 111 |
|
---|
[2143] | 112 | collectionListPanel = new JPanel();
|
---|
[2177] | 113 | collectionListPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
[2143] | 114 | collectionListPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
|
---|
[2225] | 115 | collectionLabel = new JLabel("Collection: ");
|
---|
[2198] | 116 |
|
---|
[2143] | 117 | collectionList = new JComboBox(csModel.getCollectionList()){
|
---|
[2225] | 118 | public boolean isFocusTraversable() {
|
---|
| 119 | return false;
|
---|
| 120 | }
|
---|
| 121 | };
|
---|
| 122 | collectionList.setEditable(false);
|
---|
| 123 |
|
---|
| 124 | collectionInfoButton = new JButton("Info...") {
|
---|
| 125 | public String getToolTipText(MouseEvent e) {
|
---|
| 126 | //return "more information on " + collectionList.getSelectedItem();
|
---|
| 127 | return "More information on " + csModel.getLongCollectionName((String)collectionList.getSelectedItem());
|
---|
| 128 | }
|
---|
| 129 | };
|
---|
| 130 | ToolTipManager.sharedInstance().registerComponent(collectionInfoButton);
|
---|
[2195] | 131 | collectionInfoButton.addActionListener(this);
|
---|
| 132 |
|
---|
[2143] | 133 | collectionListPanel.add(collectionLabel);
|
---|
| 134 | collectionListPanel.add(collectionList);
|
---|
[2195] | 135 | collectionListPanel.add(collectionInfoButton);
|
---|
[2198] | 136 |
|
---|
[2143] | 137 | searchTextFieldPanel = new JPanel();
|
---|
| 138 | searchTextFieldPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
|
---|
| 139 | searchTextFieldPanel.add(searchTextField);
|
---|
[2198] | 140 |
|
---|
[2143] | 141 | searchButtonPanel = new JPanel();
|
---|
| 142 | searchButtonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
---|
| 143 | searchButtonPanel.add(searchButton);
|
---|
[2198] | 144 |
|
---|
[2143] | 145 | queryFormulationPanel = new JPanel();
|
---|
| 146 | queryFormulationPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
| 147 | queryFormulationPanel.setLayout(new BoxLayout(queryFormulationPanel, BoxLayout.Y_AXIS));
|
---|
| 148 | queryFormulationPanel.add(Box.createHorizontalStrut(100));
|
---|
| 149 | queryFormulationPanel.add(collectionListPanel);
|
---|
| 150 | queryFormulationPanel.add(searchTextFieldPanel);
|
---|
| 151 | queryFormulationPanel.add(searchButtonPanel);
|
---|
[2198] | 152 |
|
---|
[2143] | 153 | resultsPanel = new JPanel();
|
---|
| 154 | resultsPanel.setLayout(new BorderLayout());
|
---|
| 155 | resultsPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
| 156 | ResultModel resultListModel = csModel.getResultsModel();
|
---|
| 157 | resultsList = new JList(resultListModel);
|
---|
| 158 | resultsList.setFont(resultsFont);
|
---|
[2177] | 159 | resultsList.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
[2143] | 160 | resultsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
---|
| 161 | scrollResultsPane = new JScrollPane(resultsList);
|
---|
| 162 | resultsPanel.add(scrollResultsPane, BorderLayout.CENTER);
|
---|
[2165] | 163 | csModel.addResult(Result.INITIAL_FAKE_RESULT);
|
---|
[2198] | 164 |
|
---|
[2143] | 165 | dataPanel = new JPanel();
|
---|
| 166 | dataPanel.setLayout(new BorderLayout());
|
---|
| 167 | dataPanel.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
|
---|
[2190] | 168 | documentPane = new JTextPane() { // to control scrolling for raw text docs
|
---|
| 169 | public boolean getScrollableTracksViewportWidth() {
|
---|
| 170 | if (getSize().width < getParent().getSize().width)
|
---|
| 171 | return true;
|
---|
| 172 | else return false;
|
---|
| 173 | }
|
---|
| 174 | public void setSize(Dimension d) {
|
---|
| 175 | if (d.width < getParent().getSize().width)
|
---|
| 176 | d.width = getParent().getSize().width;
|
---|
| 177 | super.setSize(d);
|
---|
| 178 | }
|
---|
| 179 | }; // end custom JTextPane
|
---|
[2198] | 180 |
|
---|
[2153] | 181 | documentPane.setEditable(false);
|
---|
| 182 | documentPane.setFont(docFont);
|
---|
| 183 | documentPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
| 184 | //documentPane.setPreferredSize(new Dimension(100, 100));
|
---|
| 185 |
|
---|
| 186 | scrollDataPane = new JScrollPane(documentPane);
|
---|
[2150] | 187 | scrollDataPane.setPreferredSize(new Dimension(300, 300));
|
---|
[2143] | 188 | dataPanel.add(scrollDataPane, BorderLayout.CENTER);
|
---|
[2198] | 189 |
|
---|
[2143] | 190 | parent.getRootPane().setDefaultButton(searchButton);
|
---|
[2154] | 191 |
|
---|
[2143] | 192 | resultsList.addListSelectionListener(new ResultListSelectionHandler() );
|
---|
[2154] | 193 |
|
---|
[2143] | 194 | add(Box.createHorizontalStrut(400));
|
---|
| 195 | add(queryFormulationPanel);
|
---|
| 196 | add(resultsPanel);
|
---|
| 197 | add(dataPanel);
|
---|
| 198 | searchTextField.requestFocus();
|
---|
[2142] | 199 | }
|
---|
[2153] | 200 |
|
---|
[2148] | 201 | /** respond to the user pressing the Search button */
|
---|
[2153] | 202 |
|
---|
[2149] | 203 | public void actionPerformed(ActionEvent e) {
|
---|
[2225] | 204 | String collectionName = collectionList.getSelectedItem().toString();
|
---|
[2198] | 205 | if (e.getSource() == searchButton ) {
|
---|
| 206 | // cursor not set when RETURN pressed, only when button clicked ?
|
---|
[2154] | 207 | windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
---|
| 208 | String queryString = searchTextField.getText();
|
---|
| 209 | System.err.println("Search started (" + collectionName + "): \"" + queryString + "\" ..." );
|
---|
[2149] | 210 | //send query to collection
|
---|
[2154] | 211 | NzdlQuery nzdlQuery = new NzdlQuery(queryString);
|
---|
[2149] | 212 | // return the first numResults that match
|
---|
| 213 | //query.setEndResults( 15 );
|
---|
[2154] | 214 | // "-1" means consider all the documents that match
|
---|
[2149] | 215 | nzdlQuery.setMaxDocs( -1 );
|
---|
| 216 | NzdlRequest request = new NzdlRequest( nzdlQuery );
|
---|
[2154] | 217 | NzdlResponse response = new NzdlResponse();
|
---|
[2165] | 218 |
|
---|
[2154] | 219 | nzdl.service( collectionName, request, response );
|
---|
[2149] | 220 | NzdlResultSet results = response.getResultSet();
|
---|
[2165] | 221 | ArrayList docIDs = new ArrayList(results.getDocumentIDs());
|
---|
| 222 | // System.err.println("Size of docIDs = " + docIDs.size());
|
---|
[2149] | 223 | // paired collection of docIDs and Titles - but as Sets!
|
---|
[2198] | 224 | Map titleMetaData = nzdl.getMetaData( collectionName, docIDs, "Title" );
|
---|
[2149] | 225 | // created a paired collection of docIDs and Titles - as simple Strings!
|
---|
| 226 | HashMap titleMap = new HashMap();
|
---|
| 227 | for (ListIterator i = docIDs.listIterator(); i.hasNext(); ) {
|
---|
| 228 | String docID = (String) i.next();
|
---|
[2168] | 229 | //Set titleSet = (Set) titleMetaData.get( docID );
|
---|
| 230 | ArrayList titleList = new ArrayList((Set)titleMetaData.get(docID));
|
---|
[2149] | 231 | // use the first title as *the* title
|
---|
| 232 | titleMap.put(docID, titleList.get(0));
|
---|
| 233 | } // end for
|
---|
[2154] | 234 | // update the results list
|
---|
| 235 | csModel.clearResults();
|
---|
[2165] | 236 |
|
---|
[2154] | 237 | if (docIDs.size() == 0 ) { // give some feedback for 0 results
|
---|
[2165] | 238 | csModel.addResult(Result.FAKE_RESULT);
|
---|
| 239 | documentPane.setStyledDocument(blankDoc);
|
---|
[2149] | 240 | }
|
---|
| 241 | else { // there are some results
|
---|
| 242 | Iterator docIDsIterator = docIDs.iterator();
|
---|
[2154] | 243 | while (docIDsIterator.hasNext()) {
|
---|
[2149] | 244 | String resultDocID = (String) docIDsIterator.next();
|
---|
| 245 | csModel.addResult(new Result((String)titleMap.get(resultDocID), resultDocID, collectionName ));
|
---|
| 246 | } //end while
|
---|
[2190] | 247 | if (NzdlPreferences.getInstance().getBoolean(Constants.DISPLAY_FIRST_DOC))
|
---|
[2184] | 248 | resultsList.setSelectedIndex(0); // should be under Preference control!
|
---|
[2149] | 249 | } // end else
|
---|
[2225] | 250 |
|
---|
| 251 |
|
---|
| 252 | csModel.getQueryHistoryModel().add( new QueryHistoryItem(new Query(queryString), new Date(), collectionName, "user"));
|
---|
| 253 |
|
---|
[2162] | 254 | titleMap.clear();
|
---|
| 255 | titleMetaData.clear();
|
---|
| 256 | docIDs.clear();
|
---|
[2154] | 257 | windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
---|
[2149] | 258 | } // end if
|
---|
| 259 | else {
|
---|
[2195] | 260 | if (e.getSource() == collectionInfoButton) {
|
---|
[2225] | 261 | CollectionInfoDialog cid = new CollectionInfoDialog(windowParent, collectionName, csModel);
|
---|
[2195] | 262 | }
|
---|
| 263 | else {
|
---|
| 264 | System.err.println("unknown Action event in SearchPanel");
|
---|
| 265 | }
|
---|
| 266 | }
|
---|
[2154] | 267 | } //end actionPerformed
|
---|
| 268 |
|
---|
[2149] | 269 | /** handles selection events in the results list so that when the
|
---|
| 270 | user selects a new title (say) the document contents is
|
---|
| 271 | automatically displayed in the main panel */
|
---|
[2154] | 272 |
|
---|
[2149] | 273 | class ResultListSelectionHandler implements ListSelectionListener {
|
---|
[2165] | 274 |
|
---|
| 275 | // private Result previousSelection = null;
|
---|
| 276 |
|
---|
[2149] | 277 | public void valueChanged(ListSelectionEvent e) {
|
---|
| 278 | // get the result object from the SelectedIndex
|
---|
| 279 | // assume we only get here with events from resultsList
|
---|
[2199] | 280 | int docLength = 0;
|
---|
[2165] | 281 | if (e.getValueIsAdjusting()) { return; }
|
---|
[2149] | 282 | Result result = (Result) resultsList.getSelectedValue();
|
---|
[2198] | 283 | if ((result == Result.FAKE_RESULT) || (result == Result.INITIAL_FAKE_RESULT)) {
|
---|
[2165] | 284 | documentPane.setStyledDocument( blankDoc );
|
---|
| 285 | System.err.println("clicked on fake result");
|
---|
[2198] | 286 | }
|
---|
[2222] | 287 | else { // a real result representing a real document to deal with
|
---|
[2165] | 288 |
|
---|
[2222] | 289 | windowParent.setCursor(WAIT_CURSOR);
|
---|
| 290 |
|
---|
| 291 | deleteDocContents(); // for memory/garbage collection
|
---|
| 292 |
|
---|
| 293 | StringReader sr = new StringReader(nzdl.getDocument(result.getCollectionName(), result.getDocID()));
|
---|
| 294 |
|
---|
| 295 | if (NzdlPreferences.getInstance().getBoolean(Constants.RAW_TEXT))
|
---|
| 296 | // display the document as raw text
|
---|
| 297 | displayAsRawText(sr);
|
---|
| 298 | else {
|
---|
| 299 | // treat as HTML
|
---|
| 300 | displayAsHTML(sr);
|
---|
[2225] | 301 | //htmlDoc.getImageData(nzdl, result.getCollectionName());
|
---|
[2222] | 302 | }
|
---|
| 303 |
|
---|
| 304 | windowParent.setCursor(NORMAL_CURSOR);
|
---|
| 305 | }
|
---|
| 306 | } //end valueChanged
|
---|
| 307 | }//end ResultListSelectionHandler
|
---|
| 308 |
|
---|
| 309 |
|
---|
| 310 |
|
---|
| 311 | private void deleteDocContents() {
|
---|
| 312 | //trash the old htmlDoc for memory/garbage collection
|
---|
| 313 | try {
|
---|
[2162] | 314 | if (htmlDoc != null)
|
---|
[2222] | 315 | htmlDoc.remove(0, htmlDoc.getLength());
|
---|
[2190] | 316 | if (defaultStyledDoc != null)
|
---|
| 317 | defaultStyledDoc.remove(0, defaultStyledDoc.getLength());
|
---|
[2222] | 318 | }
|
---|
| 319 | catch (Exception exception) {
|
---|
| 320 | throw new Error (exception.toString());
|
---|
| 321 | }
|
---|
| 322 | } // end deleteDocContents
|
---|
[2190] | 323 |
|
---|
[2165] | 324 |
|
---|
[2222] | 325 | public void switchToRawText() {
|
---|
| 326 | windowParent.setCursor(WAIT_CURSOR);
|
---|
| 327 | System.err.println("switching to raw text");
|
---|
| 328 | displayAsRawText(new StringReader(documentPane.getText()));
|
---|
| 329 | windowParent.setCursor(NORMAL_CURSOR);
|
---|
| 330 | }
|
---|
[2154] | 331 |
|
---|
[2222] | 332 | public void displayAsRawText(StringReader sr) {
|
---|
| 333 | defaultStyledDoc = new DefaultStyledDocument();
|
---|
| 334 | documentPane.setEditorKit(styledEditorKit);
|
---|
| 335 | try {
|
---|
| 336 | styledEditorKit.read( sr, defaultStyledDoc, 0);
|
---|
| 337 | }
|
---|
| 338 | catch (Exception e) {
|
---|
| 339 | System.err.println(e);
|
---|
| 340 | }
|
---|
| 341 | documentPane.setDocument(defaultStyledDoc);
|
---|
| 342 | setCaretToStart(defaultStyledDoc.getLength());
|
---|
| 343 | } // end displayAsRawText
|
---|
| 344 |
|
---|
| 345 |
|
---|
| 346 | public void switchToHTML() {
|
---|
| 347 | windowParent.setCursor(WAIT_CURSOR);
|
---|
| 348 | System.err.println("switching to HTML");
|
---|
| 349 | displayAsHTML(new StringReader(documentPane.getText()));
|
---|
| 350 | windowParent.setCursor(NORMAL_CURSOR);
|
---|
| 351 | }
|
---|
| 352 |
|
---|
| 353 | public void displayAsHTML(StringReader sr) {
|
---|
| 354 | htmlDoc = new GMLDocument();
|
---|
| 355 | documentPane.setEditorKit(htmlEditorKit);
|
---|
| 356 | try {
|
---|
| 357 | htmlEditorKit.read( sr, htmlDoc, 0);
|
---|
| 358 | }
|
---|
| 359 | catch (Exception e) {
|
---|
| 360 | System.err.println(e);
|
---|
| 361 | }
|
---|
| 362 | documentPane.setStyledDocument( htmlDoc );
|
---|
| 363 | setCaretToStart(htmlDoc.getLength());
|
---|
| 364 | } // end displayAsHTML
|
---|
| 365 |
|
---|
| 366 |
|
---|
| 367 | private void setCaretToStart(int docLength) {
|
---|
| 368 | // it seems as if they haven't considered
|
---|
| 369 | // documents with > MAX_INT num of chars ...
|
---|
| 370 | if (docLength > 0)
|
---|
| 371 | documentPane.setCaretPosition(1);
|
---|
| 372 | }
|
---|
| 373 |
|
---|
| 374 |
|
---|
| 375 | } //end SearchPanel
|
---|