All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ca.odell.glazedlists.swing.TextComponentMatcherEditor Maven / Gradle / Ivy

There is a newer version: 1.9.1
Show newest version
/* Glazed Lists                                                 (c) 2003-2006 */
/* http://publicobject.com/glazedlists/                      publicobject.com,*/
/*                                                     O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.swing;

import ca.odell.glazedlists.TextFilterator;
import ca.odell.glazedlists.matchers.*;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

/**
 * A MatcherEditor that matches Objects that contain the filter text located
 * within a {@link Document}. This {@link TextMatcherEditor} is directly
 * coupled with a Document and fires MatcherEditor changes in response to
 * Document changes. This matcher is fully concrete and is expected to be used
 * by Swing applications.
 *
 * 

The {@link TextComponentMatcherEditor} constructors require that either a * {@link Document} or a {@link JTextComponent} (from which a {@link Document} * is extracted) be specified. * *

The MatcherEditor registers itself as a {@link DocumentListener} on the * given Document, or {@link ActionListener} for non-live filtering. If this * MatcherEditor must be garbage collected before the underlying Document, * or JTextComponent, the listener can be unregistered by calling {@link #dispose()}. * * @author James Lemieux */ public class TextComponentMatcherEditor extends TextMatcherEditor { /** The Document that provides the filter values. */ private final Document document; /** the JTextComponent being observed for actions */ private JTextComponent textComponent; /** whether we're listening to each keystroke */ private boolean live; /** The listener attached to the given {@link #document}. */ private final FilterHandler filterHandler = new FilterHandler(); /** * Creates a TextMatcherEditor bound to the {@link Document} backing the * given textComponent with the given * textFilterator. * * @param textComponent the text component backed by the {@link Document} * that is the source of text filter values * @param textFilterator an object capable of producing Strings from the * objects being filtered. If textFilterator is * null then all filtered objects are expected to * implement {@link ca.odell.glazedlists.TextFilterable}. */ public TextComponentMatcherEditor(JTextComponent textComponent, TextFilterator textFilterator) { this(textComponent, textFilterator, true); } /** * Creates a TextMatcherEditor bound to the {@link Document} backing the * given textComponent with the given * textFilterator. * * @param textComponent the text component backed by the {@link Document} * that is the source of text filter values * @param textFilterator an object capable of producing Strings from the * objects being filtered. If textFilterator is * null then all filtered objects are expected to * implement {@link ca.odell.glazedlists.TextFilterable}. * @param live true to filter by the keystroke or false * to filter only when {@link java.awt.event.KeyEvent#VK_ENTER Enter} is pressed * within the {@link JTextComponent}. Note that non-live filtering is only * supported if textComponent is a {@link JTextField}. * @throws IllegalArgumentException if the textComponent * is not a {@link JTextField} and non-live filtering is specified. */ public TextComponentMatcherEditor(JTextComponent textComponent, TextFilterator textFilterator, boolean live) { this(textComponent, textComponent.getDocument(), textFilterator, live); } /** * Creates a TextMatcherEditor bound to the given document * with the given textFilterator. * * @param document the {@link Document} that is the source of text filter * values * @param textFilterator an object capable of producing Strings from the * objects being filtered. If textFilterator is * null then all filtered objects are expected to * implement {@link ca.odell.glazedlists.TextFilterable}. */ public TextComponentMatcherEditor(Document document, TextFilterator textFilterator) { this(null, document, textFilterator, true); } /** * This private constructor implements the actual construction work and thus * ensures that all public constructors agree on the construction logic. */ private TextComponentMatcherEditor(JTextComponent textComponent, Document document, TextFilterator textFilterator, boolean live) { super(textFilterator); this.textComponent = textComponent; this.document = document; this.live = live; registerListeners(live); // if the document is non-empty to begin with! refilter(); } /** * Whether filtering occurs by the keystroke or not. */ public boolean isLive() { return this.live; } /** * Toggle between filtering by the keystroke and not. * * @param live true to filter by the keystroke or false * to filter only when {@link java.awt.event.KeyEvent#VK_ENTER Enter} is pressed * within the {@link JTextComponent}. Note that non-live filtering is only * supported if textComponent is a {@link JTextField}. */ public void setLive(boolean live) { if(live == this.live) return; deregisterListeners(this.live); this.live = live; registerListeners(this.live); } /** * Listen live or on action performed. */ private void registerListeners(boolean live) { if(live) { this.document.addDocumentListener(this.filterHandler); } else { if(textComponent == null) throw new IllegalArgumentException("Non-live filtering supported only for JTextField (document provided)"); if(!(textComponent instanceof JTextField)) throw new IllegalArgumentException("Non-live filtering supported only for JTextField (argument class " + textComponent.getClass().getName() + ")"); JTextField textField = (JTextField)textComponent; textField.addActionListener(this.filterHandler); } } /** * Stop listening. */ private void deregisterListeners(boolean live) { if(live) { this.document.removeDocumentListener(this.filterHandler); } else { JTextField textField = (JTextField)textComponent; textField.removeActionListener(this.filterHandler); } } /** * A cleanup method which stops this MatcherEditor from listening to * changes on the underlying {@link Document}, thus freeing the * MatcherEditor or Document to be garbage collected. */ public void dispose() { deregisterListeners(this.live); } /** * Update the filter text from the contents of the Document. */ private void refilter() { try { final String text = document.getText(0, document.getLength()); String[] filters = null; // in CONTAINS mode we treat the string as whitespace delimited if (this.getMode() == CONTAINS) filters = text.split("[ \t]"); // in STARTS_WITH mode we use the string in its entirety else if (this.getMode() == STARTS_WITH) filters = new String[] {text}; setFilterText(filters); } catch (BadLocationException ble) { // this shouldn't ever, ever happen throw new RuntimeException(ble); } } /** * This class responds to any change in the Document by setting the filter * text of this TextMatcherEditor to the contents of the Document. */ private class FilterHandler implements DocumentListener, ActionListener { public void insertUpdate(DocumentEvent e) { refilter(); } public void removeUpdate(DocumentEvent e) { refilter(); } public void changedUpdate(DocumentEvent e) { refilter(); } public void actionPerformed(ActionEvent e) { refilter(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy