📄 patternmodel.java
字号:
/* * $Id: PatternModel.java,v 1.17 2005/10/12 11:26:53 kleopatra Exp $ * * 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.beans.PropertyChangeListener;import java.beans.PropertyChangeSupport;import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.regex.Pattern;import javax.swing.ActionMap;import javax.swing.UIManager;import org.jdesktop.swingx.action.AbstractActionExt;import org.jdesktop.swingx.action.BoundAction;/** * Presentation Model for Find/Filter Widgets. * <p> * * Compiles and holds a Pattern from rawText. There are different * predefined strategies to control the compilation: * * <ul> * <li> TODO: list and explain * </ul> * * Holds state for controlling the match process * for both find and filter (TODO - explain). * Relevant in all * * <ul> * <li> caseSensitive - * <li> empty - true if there's no searchString * <li> incremental - a hint to clients to react immediately * to pattern changes. * * </ul> * * Relevant in find contexts: * <ul> * <li> backwards - search direction if used in a find context * <li> wrapping - wrap over the end/start if not found * <li> foundIndex - storage for last found index * <li> autoAdjustFoundIndex - flag to indicate auto-incr/decr of foundIndex on setting. * Here the property correlates to !isIncremental() - to simplify batch vs. * incremental search ui. * </ul> * * * JW: Work-in-progress - Anchors will be factored into AnchoredSearchMode * <b>Anchors</b> By default, the scope of the pattern relative to strings * being tested are unanchored, ie, the pattern will match any part of the * tested string. Traditionally, special characters ('^' and '$') are used to * describe patterns that match the beginning (or end) of a string. If those * characters are included in the pattern, the regular expression will honor * them. However, for ease of use, two properties are included in this model * that will determine how the pattern will be evaluated when these characters * are omitted. * <p> * The <b>StartAnchored</b> property determines if the pattern must match from * the beginning of tested strings, or if the pattern can appear anywhere in the * tested string. Likewise, the <b>EndAnchored</b> property determines if the * pattern must match to the end of the tested string, or if the end of the * pattern can appear anywhere in the tested string. The default values (false * in both cases) correspond to the common database 'LIKE' operation, where the * pattern is considered to be a match if any part of the tested string matches * the pattern. * * @author Jeanette Winzenburg * @author David Hall */public class PatternModel { /** * The prefix marker to find component related properties in the * resourcebundle. */ public static final String SEARCH_PREFIX = "Search."; public static final String REGEX_UNCHANGED = "regex"; public static final String REGEX_ANCHORED = "anchored"; public static final String REGEX_WILDCARD = "wildcard"; public static final String REGEX_MATCH_RULES = "explicit"; public static final String MATCH_RULE_CONTAINS = "contains"; public static final String MATCH_RULE_EQUALS = "equals"; public static final String MATCH_RULE_ENDSWITH = "endsWith"; public static final String MATCH_RULE_STARTSWITH = "startsWith"; public static final String MATCH_BACKWARDS_ACTION_COMMAND = "backwardsSearch"; public static final String MATCH_WRAP_ACTION_COMMAND = "wrapSearch"; public static final String MATCH_CASE_ACTION_COMMAND = "matchCase"; public static final String MATCH_INCREMENTAL_ACTION_COMMAND = "matchIncremental"; private String rawText; private boolean backwards; private Pattern pattern; private int foundIndex = -1; private boolean caseSensitive; private PropertyChangeSupport propertySupport; private String regexCreatorKey; private RegexCreator regexCreator; private boolean wrapping; private ActionMap actionMap; private boolean incremental;//---------------------- misc. properties not directly related to Pattern. public int getFoundIndex() { return foundIndex; } public void setFoundIndex(int foundIndex) { int old = getFoundIndex(); updateFoundIndex(foundIndex); firePropertyChange("foundIndex", old, getFoundIndex()); } /** * * @param newFoundIndex */ protected void updateFoundIndex(int newFoundIndex) { if (newFoundIndex < 0) { this.foundIndex = newFoundIndex; return; } if (isAutoAdjustFoundIndex()) { foundIndex = backwards ? newFoundIndex -1 : newFoundIndex + 1; } else { foundIndex = newFoundIndex; } } public boolean isAutoAdjustFoundIndex() { return !isIncremental(); } public boolean isBackwards() { return backwards; } public void setBackwards(boolean backwards) { boolean old = isBackwards(); this.backwards = backwards; firePropertyChange("backwards", old, isBackwards()); setFoundIndex(getFoundIndex()); } public boolean isWrapping() { return wrapping; } public void setWrapping(boolean wrapping) { boolean old = isWrapping(); this.wrapping = wrapping; firePropertyChange("wrapping", old, isWrapping()); } public void setIncremental(boolean incremental) { boolean old = isIncremental(); this.incremental = incremental; firePropertyChange("incremental", old, isIncremental()); } public boolean isIncremental() { return incremental; } public boolean isCaseSensitive() { return caseSensitive; } public void setCaseSensitive(boolean caseSensitive) { boolean old = isCaseSensitive(); this.caseSensitive = caseSensitive; updatePattern(caseSensitive); firePropertyChange("caseSensitive", old, isCaseSensitive()); } public Pattern getPattern() { return pattern; } public String getRawText() { return rawText; } public void setRawText(String findText) { String old = getRawText(); boolean oldEmpty = isEmpty(); this.rawText = findText; updatePattern(createRegEx(findText)); firePropertyChange("rawText", old, getRawText()); firePropertyChange("empty", oldEmpty, isEmpty()); } public boolean isEmpty() { return isEmpty(getRawText()); } /** * returns a regEx for compilation into a pattern. Here: either a "contains" * (== partial find) or null if the input was empty. * * @param searchString * @return null if the input was empty, or a regex according to the internal * rules */ private String createRegEx(String searchString) { if (isEmpty(searchString)) return null; //".*"; return getRegexCreator().createRegEx(searchString); } /** * * @param s * @return */ private boolean isEmpty(String text) { return (text == null) || (text.length() == 0); } private void updatePattern(String regEx) { Pattern old = getPattern(); if (isEmpty(regEx)) { pattern = null; } else if ((old == null) || (!old.pattern().equals(regEx))) { pattern = Pattern.compile(regEx, getFlags()); } firePropertyChange("pattern", old, getPattern()); } private int getFlags() { return isCaseSensitive() ? 0 : getCaseInsensitiveFlag(); } private int getCaseInsensitiveFlag() { return Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; } private void updatePattern(boolean caseSensitive) { if (pattern == null) return; Pattern old = getPattern(); int flags = old.flags(); int flag = getCaseInsensitiveFlag();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -