001 /*
002 * $Id: JXFindBar.java 2948 2008-06-16 15:02:14Z 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 package org.jdesktop.swingx;
022
023 import java.awt.Color;
024 import java.awt.FlowLayout;
025
026 import javax.swing.JButton;
027 import javax.swing.JLabel;
028 import javax.swing.KeyStroke;
029 import javax.swing.SwingConstants;
030
031 import org.jdesktop.swingx.search.Searchable;
032
033 /**
034 * A simple low-intrusion default widget for incremental search.
035 *
036 * Actions registered (in addition to super):
037 * <ul>
038 * <li> {@link JXDialog#CLOSE_ACTION_COMMAND} - an action bound to this
039 * component's cancel method. The method itself is an empty implementation:
040 * Subclassing clients can override the method, all clients can register a
041 * custom action.
042 * </ul>
043 *
044 * Key bindings:
045 * <ul>
046 * <li> ESCAPE - calls action registered for
047 * {@link JXDialog#CLOSE_ACTION_COMMAND}
048 * </ul>
049 *
050 * This implementation uses textfield coloring as not-found visualization.
051 *
052 * <p>
053 * PENDING: the coloring needs to be read from the UIManager instead of
054 * hardcoding.
055 *
056 * <p>
057 * PENDING: the state transition of found/non-found coloring needs clean-up -
058 * there are spurious problems when re-using the same instance (as SearchFactory
059 * does).
060 *
061 * @author Jeanette Winzenburg
062 *
063 */
064 public class JXFindBar extends JXFindPanel {
065
066 protected Color previousBackgroundColor;
067
068 protected Color previousForegroundColor;
069
070 // PENDING: need to read from UIManager
071 protected Color notFoundBackgroundColor = Color.decode("#FF6666");
072
073 protected Color notFoundForegroundColor = Color.white;
074
075 protected JButton findNext;
076
077 protected JButton findPrevious;
078
079 public JXFindBar() {
080 this(null);
081 }
082
083 public JXFindBar(Searchable searchable) {
084 super(searchable);
085 getPatternModel().setIncremental(true);
086 getPatternModel().setWrapping(true);
087 }
088
089 @Override
090 public void setSearchable(Searchable searchable) {
091 super.setSearchable(searchable);
092 match();
093 }
094
095 /**
096 * here: set textfield colors to not-found colors.
097 */
098 @Override
099 protected void showNotFoundMessage() {
100 //JW: quick hack around #487-swingx - NPE in setSearchable
101 if (searchField == null) return;
102 searchField.setForeground(notFoundForegroundColor);
103 searchField.setBackground(notFoundBackgroundColor);
104 }
105
106 /**
107 * here: set textfield colors to normal.
108 */
109 @Override
110 protected void showFoundMessage() {
111 //JW: quick hack around #487-swingx - NPE in setSearchable
112 if (searchField == null) return;
113 searchField.setBackground(previousBackgroundColor);
114 searchField.setForeground(previousForegroundColor);
115 }
116
117 @Override
118 public void addNotify() {
119 super.addNotify();
120 if (previousBackgroundColor == null) {
121 previousBackgroundColor = searchField.getBackground();
122 previousForegroundColor = searchField.getForeground();
123 } else {
124 searchField.setBackground(previousBackgroundColor);
125 searchField.setForeground(previousForegroundColor);
126 }
127 }
128
129 // --------------------------- action call back
130 /**
131 * Action callback method for bound action JXDialog.CLOSE_ACTION_COMMAND.
132 *
133 * Here: does nothing. Subclasses can override to define custom "closing"
134 * behaviour. Alternatively, any client can register a custom action with
135 * the actionMap.
136 *
137 *
138 */
139 public void cancel() {
140 }
141
142 // -------------------- init
143
144 @Override
145 protected void initExecutables() {
146 getActionMap().put(JXDialog.CLOSE_ACTION_COMMAND,
147 createBoundAction(JXDialog.CLOSE_ACTION_COMMAND, "cancel"));
148 super.initExecutables();
149 }
150
151 @Override
152 protected void bind() {
153 super.bind();
154 searchField
155 .addActionListener(getAction(JXDialog.EXECUTE_ACTION_COMMAND));
156 findNext.setAction(getAction(FIND_NEXT_ACTION_COMMAND));
157 findPrevious.setAction(getAction(FIND_PREVIOUS_ACTION_COMMAND));
158 KeyStroke stroke = KeyStroke.getKeyStroke("ESCAPE");
159 getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke,
160 JXDialog.CLOSE_ACTION_COMMAND);
161 }
162
163 @Override
164 protected void build() {
165 setLayout(new FlowLayout(SwingConstants.LEADING));
166 add(searchLabel);
167 add(new JLabel(":"));
168 add(new JLabel(" "));
169 add(searchField);
170 add(findNext);
171 add(findPrevious);
172 }
173
174 @Override
175 protected void initComponents() {
176 super.initComponents();
177 findNext = new JButton();
178 findPrevious = new JButton();
179 }
180
181 }