//
// 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();
}
}
}
}