/* * #%L * Bio-Formats 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) 2006 - 2015 Open Microscopy Environment: * - Board of Regents of the University of Wisconsin-Madison * - Glencoe Software, Inc. * - University of Dundee * %% * 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, see * <http://www.gnu.org/licenses/gpl-2.0.html>. * #L% */ 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. */ 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 -- @Override 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 -- @Override 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 -- @Override public void stateChanged(ChangeEvent e) { if (e.getSource().equals(ignore)) { ignoreCase = ignore.isSelected(); } } } }