![JAR search and dependency download from the Maven repository](/logo.png)
javax.help.plaf.basic.BasicSearchNavigatorUI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javahelp Show documentation
Show all versions of javahelp Show documentation
The JavaHelp API provides a platform-independent help framework.
The newest version!
/*
* @(#)BasicSearchNavigatorUI.java 1.86 06/10/30
*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @(#) BasicSearchNavigatorUI.java 1.86 - last change made 10/30/06
*/
package javax.help.plaf.basic;
/**
* UI for Search Navigator of type JHelpListNavigator.
*
* @author Roger D. Brinkley
* @author Eduardo Pelegri-Llopart
* @author Stepan Marek
* @author Richard Gregor
* @version 1.86 10/30/06
*/
import javax.help.*;
import javax.help.search.*;
import javax.help.plaf.HelpNavigatorUI;
import javax.help.event.HelpModelListener;
import javax.help.event.HelpModelEvent;
import javax.help.search.SearchListener;
import javax.help.search.SearchEvent;
import java.util.EventObject;
import java.util.Vector;
import java.util.Enumeration;
import java.net.URL;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.net.MalformedURLException;
import javax.help.DefaultHelpModel.DefaultHighlight;
import javax.help.Map.ID;
public class BasicSearchNavigatorUI extends HelpNavigatorUI
implements HelpModelListener, SearchListener,
PropertyChangeListener, TreeSelectionListener,
ComponentListener
{
protected JHelpSearchNavigator searchnav;
protected JScrollPane sp;
protected JTree tree;
protected DefaultMutableTreeNode topNode;
protected JTextField searchparams;
protected boolean displayOptions;
protected SearchEngine helpsearch;
protected SearchQuery searchquery;
protected DefaultMutableTreeNode lastTOCnode;
private HelpSet newHelpSet;
public static ComponentUI createUI(JComponent x) {
return new BasicSearchNavigatorUI((JHelpSearchNavigator) x);
}
public BasicSearchNavigatorUI(JHelpSearchNavigator b) {
ImageIcon icon = getImageIcon(b.getNavigatorView());
if (icon != null) {
setIcon(icon);
} else {
setIcon(UIManager.getIcon("SearchNav.icon"));
}
}
ActionListener searchAction = new SearchActionListener();
private Cursor paramCursor;
private Cursor treeCursor;
private Cursor waitCursor=null;
class SearchActionListener implements ActionListener {
public synchronized void actionPerformed(ActionEvent e) {
HelpModel helpmodel = searchnav.getModel();
try {
if (paramCursor == null) {
paramCursor = searchparams.getCursor();
}
if (treeCursor == null) {
treeCursor = tree.getCursor();
}
if (waitCursor == null) {
waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
}
searchparams.setCursor(waitCursor);
tree.setCursor(waitCursor);
if (helpsearch == null) {
debug("helpsearch is null");
helpsearch = searchnav.getSearchEngine();
searchquery = helpsearch.createQuery();
searchquery.addSearchListener(BasicSearchNavigatorUI.this);
}
debug("click on search w/: "+searchparams.getText());
if (searchquery.isActive()) {
searchquery.stop();
}
searchquery.start(searchparams.getText(),searchnav.getLocale());
} catch (Exception e2) {
searchparams.setCursor(paramCursor);
tree.setCursor(treeCursor);
// more work needed here
e2.printStackTrace();
// 2 beeps
searchnav.getToolkit().beep();
searchnav.getToolkit().beep();
}
}
}
public void installUI(JComponent c) {
searchnav = (JHelpSearchNavigator)c;
HelpModel helpmodel = searchnav.getModel();
searchnav.setLayout(new BorderLayout());
searchnav.addPropertyChangeListener(this);
searchnav.addComponentListener(this);
if (helpmodel != null) {
helpmodel.addHelpModelListener(this);
}
JLabel search = new JLabel(HelpUtilities.getString(HelpUtilities.getLocale(c),
"search.findLabel"));
searchparams = new JTextField ("", 20);
search.setLabelFor(searchparams);
searchparams.addActionListener(searchAction);
JPanel box = new JPanel();
box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS));
box.add(search);
box.add(searchparams);
searchnav.add ("North", box);
topNode = new DefaultMutableTreeNode();
lastTOCnode = null;
tree = new JTree(topNode);
// public String convertValueToText(Object val
TreeSelectionModel tsm = tree.getSelectionModel();
tsm.addTreeSelectionListener(this);
tree.setShowsRootHandles(false);
tree.setRootVisible(false);
sp = new JScrollPane();
sp.getViewport().add(tree);
searchnav.add("Center", sp);
reloadData();
}
public void uninstallUI(JComponent c) {
HelpModel helpmodel = searchnav.getModel();
searchnav.removeComponentListener(this);
searchnav.removePropertyChangeListener(this);
TreeSelectionModel tsm = tree.getSelectionModel();
tsm.removeTreeSelectionListener(this);
searchnav.setLayout(null);
searchnav.removeAll();
if (helpmodel != null) {
helpmodel.removeHelpModelListener(this);
}
searchnav = null;
}
public Dimension getPreferredSize(JComponent c) {
/*
if (sp != null) {
return ((ScrollPaneLayout)sp.getLayout()).preferredLayoutSize(sp);
} else {
return new Dimension(200,100);
}
*/
return new Dimension(200,100);
}
public Dimension getMinimumSize(JComponent c) {
if (sp != null) {
return ((ScrollPaneLayout)sp.getLayout()).minimumLayoutSize(sp);
} else {
return new Dimension(100,100);
}
}
public Dimension getMaximumSize(JComponent c) {
return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
}
/**
* Indicates that there is new search data to use.
*/
private void reloadData() {
helpsearch = null;
setCellRenderer(searchnav.getNavigatorView(), tree);
// add all subhelpsets
HelpModel model = searchnav.getModel();
if (model != null) {
addSubHelpSets(model.getHelpSet());
}
}
/**
* Reloads data from new model, creates new search engine to search in new model if model
* contains view with the same name
**/
private void reloadData(HelpModel model) {
debug("reloadData using new model");
helpsearch = null;
SearchView view = null;
newHelpSet = model.getHelpSet();
SearchView oldView = (SearchView) searchnav.getNavigatorView();
String oldName = oldView.getName();
NavigatorView[] navViews = newHelpSet.getNavigatorViews();
for(int i = 0 ; i < navViews.length; i++){
if((navViews[i].getName()).equals(oldName)){
NavigatorView tempView = navViews[i];
if(tempView instanceof SearchView){
view = (SearchView) tempView;
break;
}
}
}
if(view == null)
return;
topNode.removeAllChildren();
searchnav.setSearchEngine(new MergingSearchEngine(view));
setCellRenderer(view, tree);
// add all subhelpsets
addSubHelpSets(newHelpSet);
}
/** Adds subhelpsets
*
* @param hs The HelpSet which subhelpsets will be added
*/
protected void addSubHelpSets(HelpSet hs){
for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) {
HelpSet ehs = (HelpSet) e.nextElement();
// merge views
NavigatorView[] views = ehs.getNavigatorViews();
for(int i = 0; i < views.length; i++){
if(searchnav.canMerge(views[i]))
searchnav.merge(views[i]);
}
addSubHelpSets( ehs );
}
}
/**
* Merges in the navigational data from another NavigatorView.
*/
public void merge(NavigatorView view) {
debug("merging "+view);
// redo the search if necessary
String text = searchparams.getText();
if (text != null && text.length() != 0) {
searchAction.actionPerformed(new ActionEvent(searchparams,
ActionEvent.ACTION_PERFORMED,
""));
}
}
/**
* Removes the navigational data from another NavigatorView.
*/
public void remove(NavigatorView view) {
debug("removing "+view);
// redo the search if necessary
if (searchparams.getText() != null) {
searchAction.actionPerformed(new ActionEvent(searchparams,
ActionEvent.ACTION_PERFORMED,
""));
}
}
/**
* Setd the desired cell renderer on this tree. This is exposed for redefinition
* by subclases.
*/
protected void setCellRenderer(NavigatorView view, JTree tree) {
if (view == null) {
return;
}
Map map = view.getHelpSet().getCombinedMap();
tree.setCellRenderer(new BasicSearchCellRenderer(map));
}
/**
* Processes an idChanged event. Search is different from all other
* navigators in that you while search tree is synchronized
* the highlighting doesn't occur unless selected from the search
* navigator.
*/
public void idChanged(HelpModelEvent e) {
ID id = e.getID();
URL url = e.getURL();
HelpModel helpModel = searchnav.getModel();
debug("idChanged("+e+")");
if (e.getSource() != helpModel) {
debug("Internal inconsistency!");
debug(" "+e.getSource()+" != "+helpModel);
throw new Error("Internal error");
}
TreePath s = tree.getSelectionPath();
if (s != null) {
Object o = s.getLastPathComponent();
// should require only a TreeNode
if (o instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o;
SearchTOCItem item = (SearchTOCItem) tn.getUserObject();
if (item != null) {
ID nId = item.getID();
if (nId != null && nId.equals(id)) {
return;
}
}
}
}
DefaultMutableTreeNode node = findIDorURL(topNode, id, url);
if (node == null) {
// node doesn't exist. Need to clear the selection.
debug ("node didn't exist");
tree.clearSelection();
return;
}
TreePath path = new TreePath(node.getPath());
tree.expandPath(path);
tree.setSelectionPath(path);
tree.scrollPathToVisible(path);
}
protected JHelpNavigator getHelpNavigator() {
return searchnav;
}
/**
* A value has changed. This is used as a TreeSelectionListener.
*/
public void valueChanged(TreeSelectionEvent e) {
JHelpNavigator navigator = getHelpNavigator();
HelpModel helpmodel = navigator.getModel();
debug("ValueChanged: "+e);
debug(" model: "+helpmodel);
// send selected items into navigator
TreeItem[] items = null;
TreePath[] paths = tree.getSelectionPaths();
if (paths != null) {
items = new TreeItem[paths.length];
for (int i = 0; i < paths.length; i++) {
if (paths[i] != null) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
items[i] = (TreeItem) node.getUserObject();
}
}
}
navigator.setSelectedItems(items);
// change current id only if one items is selected
if (items != null && items.length == 1) {
SearchTOCItem item = (SearchTOCItem)items[0];
if (item != null) {
if (item.getID() != null) {
try {
// navigator.setCurrentID(item.getID());
helpmodel.setCurrentID(item.getID(), item.getName(), navigator);
} catch (InvalidHelpSetContextException ex) {
System.err.println("BadID: "+item.getID());
return;
}
} else if (item.getURL() != null) {
// navigator.setCurrentURL(item.getURL());
helpmodel.setCurrentURL(item.getURL(), item.getName(), navigator);
} else {
// no ID, no URL
return;
}
if (helpmodel instanceof TextHelpModel) {
DefaultHighlight h[] = new DefaultHighlight[item.hitCount()];
int i = 0;
Enumeration enum1 = item.getSearchHits();
while (enum1.hasMoreElements()) {
SearchHit info = (SearchHit) enum1.nextElement();
h[i] = new DefaultHighlight(info.getBegin(), info.getEnd());
i++;
}
// using setHighlights() instead of removeAll + add
// avoids one highlighting event
((TextHelpModel)helpmodel).setHighlights(h);
}
}
}
}
public void propertyChange(PropertyChangeEvent event) {
debug(this + " " + "propertyChange: " + event.getSource() + " " +
event.getPropertyName());
if (event.getSource() == searchnav) {
String changeName = event.getPropertyName();
if (changeName.equals("helpModel")) {
reloadData((HelpModel)event.getNewValue());
} else if (changeName.equals("font")) {
debug ("Font change");
Font newFont = (Font)event.getNewValue();
searchparams.setFont(newFont);
RepaintManager.currentManager(searchparams).markCompletelyDirty(searchparams);
tree.setFont(newFont);
RepaintManager.currentManager(tree).markCompletelyDirty(tree);
}
// changes to UI property?
}
}
/**
* Invoked when the component's size changes.
*/
public void componentResized(ComponentEvent e) {
}
/**
* Invoked when the component's position changes.
*/
public void componentMoved(ComponentEvent e) {
}
/**
* Invoked when the component has been made visible.
*/
public void componentShown(ComponentEvent e) {
searchparams.selectAll();
searchparams.requestFocus();
}
/**
* Invoked when the component has been made invisible.
*/
public void componentHidden(ComponentEvent e) {
}
// Note - this recursive implementation may need tuning for very large TOC - epll
private DefaultMutableTreeNode findIDorURL(DefaultMutableTreeNode node,
ID id, URL url) {
SearchTOCItem item = (SearchTOCItem) node.getUserObject();
if (item != null) {
ID testID = item.getID();
if (testID != null && id != null && testID.equals(id)) {
return node;
} else {
URL testURL = item.getURL();
if (testURL != null && url != null && url.sameFile(testURL)) {
return node;
}
}
}
int size = node.getChildCount();
for (int i=0; i
*
* If you think of a one dimensional array as going from
* the lowest index on the left to the highest index on the right
* then the parameters to this function are lowest index or
* left and highest index or right. The first time you call
* this function it will be with the parameters 0, a.length - 1.
*
* @param a a DefaultMutableTreeNode array
* @param lo0 left boundary of array partition
* @param hi0 right boundary of array partition
*/
void quickSort(DefaultMutableTreeNode a[], int lo0, int hi0) {
int lo = lo0;
int hi = hi0;
int mid;
if ( hi0 > lo0)
{
/* Arbitrarily establishing partition element as the midpoint of
* the array.
*/
mid = ( lo0 + hi0 ) / 2;
// loop through the array until indices cross
while( lo <= hi )
{
/* find the first element that is greater than or equal to
* the partition element starting from the left Index.
*/
while( ( lo < hi0 ) && ( compare(a[lo],a[mid]) > 0 ))
++lo;
/* find an element that is smaller than or equal to
* the partition element starting from the right Index.
*/
while( ( hi > lo0 ) && ( compare(a[hi],a[mid]) < 0 ))
--hi;
// if the indexes have not crossed, swap
if( lo <= hi )
{
swap(a, lo, hi);
++lo;
--hi;
}
}
/* If the right index has not reached the left side of array
* must now sort the left partition.
*/
if( lo0 < hi )
quickSort( a, lo0, hi );
/* If the left index has not reached the right side of array
* must now sort the right partition.
*/
if( lo < hi0 )
quickSort( a, lo, hi0 );
}
}
private void swap(DefaultMutableTreeNode a[], int i, int j)
{
DefaultMutableTreeNode T;
T = a[i];
a[i] = a[j];
a[j] = T;
}
private int compare (DefaultMutableTreeNode node1,
DefaultMutableTreeNode node2) {
SearchTOCItem item1, item2;
double confidence1, confidence2;
int hits1, hits2;
item1 = (SearchTOCItem) node1.getUserObject();
confidence1 = item1.getConfidence();
hits1 = item1.hitCount();
item2 = (SearchTOCItem) node2.getUserObject();
confidence2 = item2.getConfidence();
hits2 = item2.hitCount();
// confidence is a penality. The lower the better
if (confidence1 > confidence2) {
// node1 is less than node2
return -1;
} else if (confidence1 < confidence2) {
// node1 is greater than node2
return 1;
} else {
// confidences are the same check the hits
if (hits1 < hits2) {
// node1 is less than node2
return -1;
} else if (hits1 > hits2) {
// node2 is greater than node2
return 1;
}
}
// nodes1 and nodes2 are equivalent
return 0;
}
public synchronized void itemsFound(SearchEvent e) {
SwingUtilities.invokeLater(new SearchItemsFound(e));
}
class SearchItemsFound implements Runnable {
SearchEvent e;
SearchItemsFound (SearchEvent e) {
this.e = e;
}
public void run() {
SearchTOCItem tocitem;
Vector nodes = new Vector();
// Add all the children of the topnode to the Vector of nodes.
Enumeration children = topNode.children();
while (children.hasMoreElements()) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement();
nodes.addElement(node);
}
debug ("items found");
HelpModel helpmodel = searchnav.getModel();
HelpSet hs = helpmodel.getHelpSet();
debug("hs:"+hs.toString());
Map map = hs.getCombinedMap();
Enumeration itemEnum = e.getSearchItems();
while (itemEnum.hasMoreElements()) {
SearchItem item = (SearchItem) itemEnum.nextElement();
debug(" item: "+item);
URL url;
try {
url = new URL(item.getBase(), item.getFilename());
} catch (MalformedURLException me) {
System.err.println ("Failed to create URL from " + item.getBase() + "|" +
item.getFilename());
continue;
}
boolean foundNode = false;
DefaultMutableTreeNode node = null;
Enumeration nodesEnum = nodes.elements();
while (nodesEnum.hasMoreElements()) {
node = (DefaultMutableTreeNode)nodesEnum.nextElement();
tocitem = (SearchTOCItem) node.getUserObject();
URL testURL = tocitem.getURL();
if (testURL != null && url != null && url.sameFile(testURL)) {
tocitem = (SearchTOCItem) node.getUserObject();
tocitem.addSearchHit(new SearchHit(item.getConfidence(),
item.getBegin(),
item.getEnd()));
foundNode = true;
break;
}
}
if (!foundNode) {
tocitem = new SearchTOCItem(item);
node = new DefaultMutableTreeNode(tocitem);
nodes.addElement(node);
}
}
reorder(nodes);
((DefaultTreeModel)tree.getModel()).reload();
}
}
public synchronized void searchStarted(SearchEvent e) {
debug ("search Started");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TreeSelectionModel tsm = tree.getSelectionModel();
tsm.clearSelection();
topNode.removeAllChildren();
((DefaultTreeModel)tree.getModel()).reload();
tree.invalidate();
tree.repaint();
}
});
}
public synchronized void searchFinished(SearchEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TreeSelectionModel tsm = tree.getSelectionModel();
if (lastTOCnode == null && topNode.getChildCount() > 0) {
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) topNode.getFirstChild();
if (node != null) {
tsm.clearSelection();
tsm.setSelectionPath(new TreePath(node.getPath()));
}
} else {
// beep
searchnav.getToolkit().beep();
}
searchparams.setCursor(paramCursor);
tree.setCursor(treeCursor);
}
});
return;
}
/**
* For printf debugging.
*/
private static boolean debug = false;
private static void debug(String str) {
if (debug) {
System.out.println("BasicSearchNavigatorUI: " + str);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy