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    }