001 /*
002 * $Id: JXSearchPanel.java 3378 2009-07-08 11:07:58Z kleopatra $
003 *
004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020 */
021
022 package org.jdesktop.swingx;
023
024 import java.util.ArrayList;
025 import java.util.Iterator;
026 import java.util.List;
027 import java.util.regex.Pattern;
028
029 import javax.swing.ComboBoxModel;
030 import javax.swing.DefaultComboBoxModel;
031 import javax.swing.JComboBox;
032
033 import org.jdesktop.swingx.decorator.Highlighter;
034 import org.jdesktop.swingx.decorator.PatternMatcher;
035
036 /**
037 * <p>
038 * {@code JXSearchPanel} provides complex searching features. Users are able to
039 * specify searching rules, enter searching text (including regular
040 * expressions), and toggle case-sensitivity.
041 * </p>
042 * <p>
043 * One of the main features that {@code JXSearchPanel} provides is the ability
044 * to update {@link PatternMatcher}s. To highlight text with a
045 * {@link Highlighter}, you need to update the highlighter via a pattern
046 * matcher.
047 * </p>
048 * <pre>
049 * public class PatternHandler implements PatternMatcher {
050 *
051 * private Highlighter highlighter;
052 *
053 * private Pattern pattern;
054 *
055 * public void setPattern(Pattern pattern) {
056 * this.pattern = pattern;
057 * highlighter.setHighlightPredicate(new PatternPredicate(pattern));
058 * }
059 *
060 * }
061 * </pre>
062 * <p>
063 * TODO: allow custom PatternModel and/or access to configuration of bound
064 * PatternModel.
065 * </p>
066 * <p>
067 * TODO: fully support control of multiple PatternMatchers.
068 * </p>
069 *
070 * @author Ramesh Gupta
071 * @author Jeanette Winzenburg
072 */
073 public class JXSearchPanel extends AbstractPatternPanel {
074 /**
075 * The action command key.
076 */
077 public static final String MATCH_RULE_ACTION_COMMAND = "selectMatchRule";
078
079 private JComboBox searchCriteria;
080
081 private List<PatternMatcher> patternMatchers;
082
083
084 /**
085 * Creates a search panel.
086 */
087 public JXSearchPanel() {
088 initComponents();
089 build();
090 initActions();
091 bind();
092 getPatternModel().setIncremental(true);
093 }
094
095 //----------------- accessing public properties
096
097 /**
098 * Adds a pattern matcher.
099 *
100 * @param matcher
101 * the matcher to add.
102 */
103 public void addPatternMatcher(PatternMatcher matcher) {
104 getPatternMatchers().add(matcher);
105 updateFieldName(matcher);
106 }
107
108 /**
109 * sets the PatternFilter control.
110 *
111 * PENDING: change to do a addPatternMatcher to enable multiple control.
112 *
113 */
114 // public void setPatternFilter(PatternFilter filter) {
115 // getPatternMatchers().add(filter);
116 // updateFieldName(filter);
117 // }
118
119 /**
120 * set the label of the search combo.
121 *
122 * @param name
123 * the label
124 */
125 public void setFieldName(String name) {
126 String old = searchLabel.getText();
127 searchLabel.setText(name);
128 firePropertyChange("fieldName", old, searchLabel.getText());
129 }
130
131 /**
132 * returns the label of the search combo.
133 *
134 */
135 public String getFieldName() {
136 return searchLabel.getText();
137 }
138
139 /**
140 * returns the current compiled Pattern.
141 *
142 * @return the current compiled <code>Pattern</code>
143 */
144 public Pattern getPattern() {
145 return patternModel.getPattern();
146 }
147
148 /**
149 * @param matcher
150 */
151 protected void updateFieldName(PatternMatcher matcher) {
152
153 // if (matcher instanceof PatternFilter) {
154 // PatternFilter filter = (PatternFilter) matcher;
155 // searchLabel.setText(filter.getColumnName());
156 // } else {
157 if (searchLabel.getText().length() == 0) { // ugly hack
158 searchLabel.setText("Field");
159 /** TODO: Remove this hack!!! */
160 // }
161 }
162 }
163
164 // ---------------- action callbacks
165
166 /**
167 * Updates the pattern matchers.
168 */
169 @Override
170 public void match() {
171 for (Iterator<PatternMatcher> iter = getPatternMatchers().iterator(); iter.hasNext();) {
172 iter.next().setPattern(getPattern());
173
174 }
175 }
176
177 /**
178 * set's the PatternModel's MatchRule to the selected in combo.
179 *
180 * NOTE: this
181 * is public as an implementation side-effect!
182 * No need to ever call directly.
183 */
184 public void updateMatchRule() {
185 getPatternModel().setMatchRule(
186 (String) searchCriteria.getSelectedItem());
187 }
188
189 private List<PatternMatcher> getPatternMatchers() {
190 if (patternMatchers == null) {
191 patternMatchers = new ArrayList<PatternMatcher>();
192 }
193 return patternMatchers;
194 }
195
196 //---------------- init actions and model
197
198 @Override
199 protected void initExecutables() {
200 super.initExecutables();
201 getActionMap().put(MATCH_RULE_ACTION_COMMAND,
202 createBoundAction(MATCH_RULE_ACTION_COMMAND, "updateMatchRule"));
203 }
204
205
206 //--------------------- binding support
207
208
209
210 /**
211 * bind the components to the patternModel/actions.
212 */
213 @Override
214 protected void bind() {
215 super.bind();
216 List matchRules = getPatternModel().getMatchRules();
217 // PENDING: map rules to localized strings
218 ComboBoxModel model = new DefaultComboBoxModel(matchRules.toArray());
219 model.setSelectedItem(getPatternModel().getMatchRule());
220 searchCriteria.setModel(model);
221 searchCriteria.setAction(getAction(MATCH_RULE_ACTION_COMMAND));
222
223 }
224
225
226
227 //------------------------ init ui
228
229 /**
230 * build container by adding all components.
231 * PRE: all components created.
232 */
233 private void build() {
234 add(searchLabel);
235 add(searchCriteria);
236 add(searchField);
237 add(matchCheck);
238 }
239
240 /**
241 * create contained components.
242 *
243 *
244 */
245 @Override
246 protected void initComponents() {
247 super.initComponents();
248 searchCriteria = new JComboBox();
249 }
250
251
252 }