001/* 002 * $Id: JXSearchPanel.java 4158 2012-02-03 18:29:40Z kschaefe $ 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 022package org.jdesktop.swingx; 023 024import java.util.ArrayList; 025import java.util.HashMap; 026import java.util.Iterator; 027import java.util.List; 028import java.util.Locale; 029import java.util.Map; 030import java.util.regex.Pattern; 031 032import javax.swing.ComboBoxModel; 033import javax.swing.DefaultComboBoxModel; 034 035import org.jdesktop.beans.JavaBean; 036import org.jdesktop.swingx.decorator.Highlighter; 037import org.jdesktop.swingx.renderer.DefaultListRenderer; 038import org.jdesktop.swingx.renderer.LocalizableStringValue; 039import org.jdesktop.swingx.renderer.StringValue; 040import org.jdesktop.swingx.search.PatternMatcher; 041import org.jdesktop.swingx.search.PatternModel; 042/** 043 * <p> 044 * {@code JXSearchPanel} provides complex searching features. Users are able to 045 * specify searching rules, enter searching text (including regular 046 * expressions), and toggle case-sensitivity. 047 * </p> 048 * <p> 049 * One of the main features that {@code JXSearchPanel} provides is the ability 050 * to update {@link PatternMatcher}s. To highlight text with a 051 * {@link Highlighter}, you need to update the highlighter via a pattern 052 * matcher. 053 * </p> 054 * <pre> 055 * public class PatternHandler implements PatternMatcher { 056 * 057 * private Highlighter highlighter; 058 * 059 * private Pattern pattern; 060 * 061 * public void setPattern(Pattern pattern) { 062 * this.pattern = pattern; 063 * highlighter.setHighlightPredicate(new PatternPredicate(pattern)); 064 * } 065 * 066 * } 067 * </pre> 068 * <p> 069 * TODO: allow custom PatternModel and/or access to configuration of bound 070 * PatternModel. 071 * </p> 072 * <p> 073 * TODO: fully support control of multiple PatternMatchers. 074 * </p> 075 * 076 * @author Ramesh Gupta 077 * @author Jeanette Winzenburg 078 */ 079@JavaBean 080public class JXSearchPanel extends AbstractPatternPanel { 081 /** 082 * The action command key. 083 */ 084 public static final String MATCH_RULE_ACTION_COMMAND = "selectMatchRule"; 085 086 private JXComboBox searchCriteria; 087 088 private List<PatternMatcher> patternMatchers; 089 090 091 /** 092 * Creates a search panel. 093 */ 094 public JXSearchPanel() { 095 initComponents(); 096 build(); 097 initActions(); 098 bind(); 099 getPatternModel().setIncremental(true); 100 } 101 102//----------------- accessing public properties 103 104 /** 105 * Adds a pattern matcher. 106 * 107 * @param matcher 108 * the matcher to add. 109 */ 110 public void addPatternMatcher(PatternMatcher matcher) { 111 getPatternMatchers().add(matcher); 112 updateFieldName(matcher); 113 } 114 115 /** 116 * sets the PatternFilter control. 117 * 118 * PENDING: change to do a addPatternMatcher to enable multiple control. 119 * 120 */ 121// public void setPatternFilter(PatternFilter filter) { 122// getPatternMatchers().add(filter); 123// updateFieldName(filter); 124// } 125 126 /** 127 * set the label of the search combo. 128 * 129 * @param name 130 * the label 131 */ 132 public void setFieldName(String name) { 133 String old = searchLabel.getText(); 134 searchLabel.setText(name); 135 firePropertyChange("fieldName", old, searchLabel.getText()); 136 } 137 138 /** 139 * returns the label of the search combo. 140 * 141 */ 142 public String getFieldName() { 143 return searchLabel.getText(); 144 } 145 146 /** 147 * returns the current compiled Pattern. 148 * 149 * @return the current compiled <code>Pattern</code> 150 */ 151 public Pattern getPattern() { 152 return patternModel.getPattern(); 153 } 154 155 /** 156 * @param matcher 157 */ 158 protected void updateFieldName(PatternMatcher matcher) { 159 160// if (matcher instanceof PatternFilter) { 161// PatternFilter filter = (PatternFilter) matcher; 162// searchLabel.setText(filter.getColumnName()); 163// } else { 164 if (searchLabel.getText().length() == 0) { // ugly hack 165 searchLabel.setText("Field"); 166 /** TODO: Remove this hack!!! */ 167// } 168 } 169 } 170 171 // ---------------- action callbacks 172 173 /** 174 * Updates the pattern matchers. 175 */ 176 @Override 177 public void match() { 178 for (Iterator<PatternMatcher> iter = getPatternMatchers().iterator(); iter.hasNext();) { 179 iter.next().setPattern(getPattern()); 180 181 } 182 } 183 184 /** 185 * set's the PatternModel's MatchRule to the selected in combo. 186 * 187 * NOTE: this 188 * is public as an implementation side-effect! 189 * No need to ever call directly. 190 */ 191 public void updateMatchRule() { 192 getPatternModel().setMatchRule( 193 (String) searchCriteria.getSelectedItem()); 194 } 195 196 private List<PatternMatcher> getPatternMatchers() { 197 if (patternMatchers == null) { 198 patternMatchers = new ArrayList<PatternMatcher>(); 199 } 200 return patternMatchers; 201 } 202 203 //---------------- init actions and model 204 205 @Override 206 protected void initExecutables() { 207 super.initExecutables(); 208 getActionMap().put(MATCH_RULE_ACTION_COMMAND, 209 createBoundAction(MATCH_RULE_ACTION_COMMAND, "updateMatchRule")); 210 } 211 212 213 //--------------------- binding support 214 215 216 217 /** 218 * bind the components to the patternModel/actions. 219 */ 220 @Override 221 protected void bind() { 222 super.bind(); 223 List<?> matchRules = getPatternModel().getMatchRules(); 224 // PENDING: map rules to localized strings 225 ComboBoxModel model = new DefaultComboBoxModel(matchRules.toArray()); 226 model.setSelectedItem(getPatternModel().getMatchRule()); 227 searchCriteria.setModel(model); 228 searchCriteria.setAction(getAction(MATCH_RULE_ACTION_COMMAND)); 229 searchCriteria.setRenderer(new DefaultListRenderer(createStringValue(getLocale()))); 230 231 } 232 233 234 private StringValue createStringValue(Locale locale) { 235 // TODO Auto-generated method stub 236 Map<Object, String> keys = new HashMap<Object, String>(); 237 keys.put(PatternModel.MATCH_RULE_CONTAINS, 238 PatternModel.MATCH_RULE_CONTAINS); 239 keys.put(PatternModel.MATCH_RULE_ENDSWITH, 240 PatternModel.MATCH_RULE_ENDSWITH); 241 keys.put(PatternModel.MATCH_RULE_EQUALS, 242 PatternModel.MATCH_RULE_EQUALS); 243 keys.put(PatternModel.MATCH_RULE_STARTSWITH, 244 PatternModel.MATCH_RULE_STARTSWITH); 245 return new LocalizableStringValue(keys, PatternModel.SEARCH_PREFIX, locale); 246 } 247 248 /** 249 * {@inheritDoc} 250 */ 251 @Override 252 protected void updateLocaleState(Locale locale) { 253 // TODO Auto-generated method stub 254 super.updateLocaleState(locale); 255 searchCriteria.setRenderer(new DefaultListRenderer(createStringValue(locale))); 256 } 257 258 //------------------------ init ui 259 /** 260 * build container by adding all components. 261 * PRE: all components created. 262 */ 263 private void build() { 264 add(searchLabel); 265 add(searchCriteria); 266 add(searchField); 267 add(matchCheck); 268 } 269 270 /** 271 * create contained components. 272 * 273 * 274 */ 275 @Override 276 protected void initComponents() { 277 super.initComponents(); 278 searchCriteria = new JXComboBox(); 279 } 280 281 282}