/*
JMeld is a visual diff and merge tool.
Copyright (C) 2007 Kees Kuip
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 Street, Fifth Floor,
Boston, MA 02110-1301 USA
*/
package org.jmeld.ui.search;
import org.jmeld.ui.AbstractBarDialog;
import org.jmeld.ui.JMeldPanel;
import org.jmeld.ui.util.ImageUtil;
import org.jmeld.util.StringUtil;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.*;
public class SearchBarDialog
extends AbstractBarDialog
{
// class variables:
private static final String CP_FOREGROUND = "JMeld.foreground";
private static final String CP_BACKGROUND = "JMeld.background";
// Instance variables:
private JTextField searchField;
private JLabel searchResult;
private Timer timer;
public SearchBarDialog(JMeldPanel meldPanel)
{
super(meldPanel);
}
protected void init()
{
JButton closeButton;
JButton previousButton;
JButton nextButton;
setLayout(new FlowLayout(FlowLayout.LEADING));
// Close the search dialog:
closeButton = new JButton(ImageUtil.getImageIcon("jmeld_close"));
closeButton.setRolloverIcon(ImageUtil.getImageIcon("jmeld_close-rollover"));
closeButton.setPressedIcon(ImageUtil.getImageIcon("jmeld_close-pressed"));
closeButton.addActionListener(getCloseAction());
initButton(closeButton);
closeButton.setBorder(null);
// Incremental search:
searchField = new JTextField(15);
searchField.getDocument().addDocumentListener(getSearchAction());
searchField.addKeyListener(getSearchKeyAction());
// Find previous match:
previousButton = new JButton("Previous", ImageUtil
.getImageIcon("stock_data-previous"));
previousButton.addActionListener(getPreviousAction());
initButton(previousButton);
// Find next match:
nextButton = new JButton("Next", ImageUtil.getImageIcon("stock_data-next"));
nextButton.addActionListener(getNextAction());
initButton(nextButton);
searchResult = new JLabel();
initButton(previousButton);
add(closeButton);
add(Box.createHorizontalStrut(5));
add(new JLabel("Find:"));
add(searchField);
add(previousButton);
add(nextButton);
add(Box.createHorizontalStrut(10));
add(searchResult);
timer = new Timer(500, executeSearch());
timer.setRepeats(false);
}
private void initButton(AbstractButton button)
{
button.setFocusable(false);
button.setBorderPainted(false);
button.setBorder(new EmptyBorder(0, 5, 0, 5));
}
public SearchCommand getCommand()
{
return new SearchCommand(searchField.getText(), false);
}
public void setSearchText(String searchText)
{
if (StringUtil.isEmpty(searchText))
{
return;
}
// You can start a search by selecting some text and then
// hit CTRL-F. But if you have selected more than x
// characters you probably don't want to search for that.
// So I choose to ignore those texts.
if (searchText.length() > 50)
{
return;
}
searchField.setText(searchText);
}
public void _activate()
{
searchField.requestFocus();
searchField.selectAll();
if (!StringUtil.isEmpty(searchField.getText()))
{
timer.restart();
}
}
public void _deactivate()
{
}
private DocumentListener getSearchAction()
{
return new DocumentListener()
{
public void changedUpdate(DocumentEvent e)
{
timer.restart();
}
public void insertUpdate(DocumentEvent e)
{
timer.restart();
}
public void removeUpdate(DocumentEvent e)
{
timer.restart();
}
};
}
private ActionListener executeSearch()
{
return new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
boolean notFound;
Color color;
String searchText;
SearchHits searchHits;
searchText = searchField.getText();
searchHits = getMeldPanel().doSearch(null);
notFound = (searchHits == null || searchHits.getSearchHits().size() == 0);
if (notFound)
{
// I would love to set the background to red and foreground
// to white but the jdk won't let me set the background if
// GTK look&feel is chosen.
if (searchField.getForeground() != Color.red)
{
// Remember the original colors:
searchField.putClientProperty(CP_FOREGROUND, searchField
.getForeground());
// Set the new colors:
searchField.setForeground(Color.red);
}
searchResult.setIcon(ImageUtil.getImageIcon("bullet-warning"));
searchResult.setText("Phrase not found");
}
else
{
// Set the original colors:
color = (Color) searchField.getClientProperty(CP_FOREGROUND);
if (color != null)
{
searchField.setForeground(color);
searchField.putClientProperty(CP_FOREGROUND, null);
}
if (!StringUtil.isEmpty(searchResult.getText()))
{
searchResult.setIcon(null);
searchResult.setText("");
}
}
}
};
}
private KeyListener getSearchKeyAction()
{
return new KeyAdapter()
{
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
getMeldPanel().doNextSearch(null);
}
}
};
}
private ActionListener getCloseAction()
{
return new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
getMeldPanel().doStopSearch(null);
}
};
}
private ActionListener getPreviousAction()
{
return new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
getMeldPanel().doPreviousSearch(null);
}
};
}
private ActionListener getNextAction()
{
return new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
getMeldPanel().doNextSearch(null);
}
};
}
}