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 }