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