// // SearchableWindow.java // /* LOCI Plugins for ImageJ: a collection of ImageJ plugins including the Bio-Formats Importer, Bio-Formats Exporter, Bio-Formats Macro Extensions, Data Browser and Stack Slicer. Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden and Christopher Peterson. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package loci.plugins.util; import ij.text.TextPanel; import ij.text.TextWindow; import java.awt.Component; import java.awt.Dimension; import java.awt.Menu; import java.awt.MenuBar; import java.awt.MenuItem; import java.awt.Scrollbar; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; /** * Text panel with search capabilities. * * <dl><dt><b>Source code:</b></dt> * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/loci-plugins/src/loci/plugins/util/SearchableWindow.java">Trac</a>, * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/loci-plugins/src/loci/plugins/util/SearchableWindow.java;hb=HEAD">Gitweb</a></dd></dl> */ public class SearchableWindow extends TextWindow { protected TextPanel panel; protected int index; // -- Constructor -- public SearchableWindow(String title, String headings, String data, int w, int h) { super(title, headings, data, w, h); index = -1; panel = getTextPanel(); MenuBar menubar = getMenuBar(); Menu menu = menubar.getMenu(0); MenuItem search = new MenuItem("Search..."); search.setActionCommand("search"); search.addActionListener(this); menu.add(search); } // -- ActionListener API methods -- public void actionPerformed(ActionEvent e) { if ("search".equals(e.getActionCommand())) { new SearchBox(this); } else panel.actionPerformed(e); } // -- SearchableWindow API methods -- public void selectLine(int index) { //int ys = panel.getFontMetrics(getFont()).getHeight() + 2; //int y = ys * (index + 1) + 2; // absolute y coordinate //int totalHeight = ys * panel.getLineCount(); Scrollbar ss = null; Component[] components = panel.getComponents(); for (int i=0; i<components.length; i++) { if (components[i] instanceof Scrollbar) { Scrollbar s = (Scrollbar) components[i]; if (s.getOrientation() == Scrollbar.VERTICAL) { ss = s; } } } //int height = panel.getHeight(); // convert absolute y value to scrollbar and relative y coordinates int min = ss.getMinimum(); int scrollValue = min + index; ss.setValue(scrollValue); panel.adjustmentValueChanged(null); } // -- Helper class -- class SearchBox extends JDialog implements ActionListener, ChangeListener { private JTextField searchBox; private JCheckBox ignore; private boolean ignoreCase; private SearchableWindow searchPane; public SearchBox(SearchableWindow searchPane) { setTitle("Search..."); this.searchPane = searchPane; FormLayout layout = new FormLayout("pref,pref:grow,pref,pref:grow,pref", "pref,pref:grow,pref,pref:grow,pref,pref:grow,pref"); JPanel panel = new JPanel(layout); CellConstraints cc = new CellConstraints(); searchBox = new JTextField(); ignore = new JCheckBox("Ignore Case", false); ignore.addChangeListener(this); JButton next = new JButton("Find Next"); next.setActionCommand("next"); next.addActionListener(this); JButton previous = new JButton("Find Previous"); previous.setActionCommand("previous"); previous.addActionListener(this); JButton cancel = new JButton("Cancel"); cancel.setActionCommand("cancel"); cancel.addActionListener(this); panel.add(searchBox, cc.xy(2, 2)); panel.add(ignore, cc.xy(2, 4)); panel.add(next, cc.xy(4, 2)); panel.add(previous, cc.xy(4, 4)); panel.add(cancel, cc.xywh(2, 6, 3, 1)); panel.setSize(new Dimension(350, 200)); setContentPane(panel); setDefaultCloseOperation(DISPOSE_ON_CLOSE); setSize(new Dimension(350, 200)); setVisible(true); } // -- ActionListener API methods -- public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); if (cmd.equals("next")) { searchPane.panel.resetSelection(); String text = searchBox.getText(); boolean found = false; int original = searchPane.index; while (!found) { searchPane.index++; if (searchPane.index >= searchPane.panel.getLineCount()) { searchPane.index = 0; } if (searchPane.index == original) return; String line = searchPane.panel.getLine(searchPane.index); found = ignoreCase ? line.toLowerCase().indexOf( text.toLowerCase()) >= 0 : line.indexOf(text) >= 0; } searchPane.selectLine(searchPane.index); } else if (cmd.equals("previous")) { searchPane.panel.resetSelection(); String text = searchBox.getText(); boolean found = false; int original = searchPane.index; while (!found) { searchPane.index--; if (searchPane.index < 0) { searchPane.index = searchPane.panel.getLineCount() - 1; } if (searchPane.index == original) return; String line = searchPane.panel.getLine(searchPane.index); found = ignoreCase ? line.toLowerCase().indexOf( text.toLowerCase()) >= 0 : line.indexOf(text) >= 0; } searchPane.selectLine(searchPane.index); } else if (cmd.equals("cancel")) { dispose(); } } // -- ChangeListener API methods -- public void stateChanged(ChangeEvent e) { if (e.getSource().equals(ignore)) { ignoreCase = ignore.isSelected(); } } } }