org.jdesktop.swingx.JXFindPanel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swingx-all Show documentation
Show all versions of swingx-all Show documentation
A Maven project to aggregate all modules into a single artifact.
/*
* $Id$
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jdesktop.swingx;
import java.awt.Component;
import java.util.Locale;
import java.util.regex.Pattern;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import org.jdesktop.beans.JavaBean;
import org.jdesktop.swingx.search.PatternModel;
import org.jdesktop.swingx.search.Searchable;
/**
* {@code JXFindPanel} is a basic find panel suitable for use in dialogs. It
* offers case-sensitivity, wrapped searching, and reverse searching.
*
* @author unascribed from JDNC
* @author Jeanette Winzenburg
*/
@JavaBean
public class JXFindPanel extends AbstractPatternPanel {
public static final String FIND_NEXT_ACTION_COMMAND = "findNext";
public static final String FIND_PREVIOUS_ACTION_COMMAND = "findPrevious";
protected Searchable searchable;
protected JCheckBox wrapCheck;
protected JCheckBox backCheck;
private boolean initialized;
/**
* Default constructor for the find panel. Constructs panel not targeted to
* any component.
*/
public JXFindPanel() {
this(null);
}
/**
* Construct search panel targeted to specific Searchable
component.
*
* @param searchable Component where search widget will try to locate and select
* information using methods of the Searchable
interface.
*/
public JXFindPanel(Searchable searchable) {
setName(getUIString(SEARCH_TITLE));
setSearchable(searchable);
initActions();
}
/**
* Sets the Searchable targeted of this find widget.
* Triggers a search with null pattern to release the old
* searchable, if any.
*
* @param searchable Component where search widget will try to locate and select
* information using methods of the {@link Searchable Searchable} interface.
*/
public void setSearchable(Searchable searchable) {
if ((this.searchable != null) && this.searchable.equals(searchable)) return;
Searchable old = this.searchable;
if (old != null) {
old.search((Pattern) null);
}
this.searchable = searchable;
getPatternModel().setFoundIndex(-1);
firePropertyChange("searchable", old, this.searchable);
}
/**
* Notifies this component that it now has a parent component.
* When this method is invoked, the chain of parent components is
* set up with KeyboardAction
event listeners.
*/
@Override
public void addNotify() {
init();
super.addNotify();
}
/**
* Initializes component and its listeners and models.
*/
protected void init() {
if (initialized) return;
initialized = true;
initComponents();
build();
bind();
}
//------------------ support synch the model <--> components
/**
* Configure and bind components to/from PatternModel.
*/
@Override
protected void bind() {
super.bind();
getActionContainerFactory().configureButton(wrapCheck,
getAction(PatternModel.MATCH_WRAP_ACTION_COMMAND),
null);
getActionContainerFactory().configureButton(backCheck,
getAction(PatternModel.MATCH_BACKWARDS_ACTION_COMMAND),
null);
}
/**
* called from listening to empty property of PatternModel.
*
* this implementation calls super and additionally synchs the
* enabled state of FIND_NEXT_ACTION_COMMAND, FIND_PREVIOUS_ACTION_COMMAND
* to !empty.
*/
@Override
protected void refreshEmptyFromModel() {
super.refreshEmptyFromModel();
boolean enabled = !getPatternModel().isEmpty();
getAction(FIND_NEXT_ACTION_COMMAND).setEnabled(enabled);
getAction(FIND_PREVIOUS_ACTION_COMMAND).setEnabled(enabled);
}
//--------------------- action callbacks
/**
* Action callback for Find action.
* Find next/previous match using current setting of direction flag.
*
*/
@Override
public void match() {
doFind();
}
/**
* Action callback for FindNext action.
* Sets direction flag to forward and calls find.
*/
public void findNext() {
getPatternModel().setBackwards(false);
doFind();
}
/**
* Action callback for FindPrevious action.
* Sets direction flag to previous and calls find.
*/
public void findPrevious() {
getPatternModel().setBackwards(true);
doFind();
}
/**
* Common standalone method to perform search. Used by the action callback methods
* for Find/FindNext/FindPrevious actions. Finds next/previous match using current
* setting of direction flag. Result is being reporred using showFoundMessage and
* showNotFoundMessage methods respectively.
*
* @see #match
* @see #findNext
* @see #findPrevious
*/
protected void doFind() {
if (searchable == null)
return;
int foundIndex = doSearch();
boolean notFound = (foundIndex == -1) && !getPatternModel().isEmpty();
if (notFound) {
if (getPatternModel().isWrapping()) {
notFound = doSearch() == -1;
}
}
if (notFound) {
showNotFoundMessage();
} else {
showFoundMessage();
}
}
/**
* Performs search and returns index of the next match.
*
* @return Index of the next match in document.
*/
protected int doSearch() {
int foundIndex = searchable.search(getPatternModel().getPattern(),
getPatternModel().getFoundIndex(), getPatternModel().isBackwards());
getPatternModel().setFoundIndex(foundIndex);
return getPatternModel().getFoundIndex();
// first try on #236-swingx - foundIndex wrong in backwards search.
// re-think: autoIncrement in PatternModel?
// return foundIndex;
}
/**
* Report that suitable match is found.
*/
protected void showFoundMessage() {
}
/**
* Report that no match is found.
*/
protected void showNotFoundMessage() {
JOptionPane.showMessageDialog(this, getUIString("notFound"));
}
//-------------- dynamic Locale support
@Override
protected void updateLocaleState(Locale locale) {
super.updateLocaleState(locale);
setName(getUIString(SEARCH_TITLE, locale));
}
//-------------------------- initial
/**
* creates and registers all "executable" actions.
* Meaning: the actions bound to a callback method on this.
*/
@Override
protected void initExecutables() {
getActionMap().put(FIND_NEXT_ACTION_COMMAND,
createBoundAction(FIND_NEXT_ACTION_COMMAND, "findNext"));
getActionMap().put(FIND_PREVIOUS_ACTION_COMMAND,
createBoundAction(FIND_PREVIOUS_ACTION_COMMAND, "findPrevious"));
super.initExecutables();
}
//----------------------------- init ui
/**
* Create and initialize components.
*/
@Override
protected void initComponents() {
super.initComponents();
wrapCheck = new JCheckBox();
backCheck = new JCheckBox();
}
/**
* Compose and layout all the subcomponents.
*/
protected void build() {
Box lBox = new Box(BoxLayout.LINE_AXIS);
lBox.add(searchLabel);
lBox.add(new JLabel(":"));
lBox.add(new JLabel(" "));
lBox.setAlignmentY(Component.TOP_ALIGNMENT);
Box rBox = new Box(BoxLayout.PAGE_AXIS);
rBox.add(searchField);
rBox.add(matchCheck);
rBox.add(wrapCheck);
rBox.add(backCheck);
rBox.setAlignmentY(Component.TOP_ALIGNMENT);
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
add(lBox);
add(rBox);
}
}