/******************************************************************************* * Copyright (c) 2001, 2010 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/epl-v10.html * * Contributors: * Matthew Reeder * - Initial API and implementation * Flemming N. Larsen * - Minor optimizations *******************************************************************************/ package net.sf.robocode.ui.editor; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Matthew Reeder (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class FindReplaceDialog extends JDialog implements ActionListener { private JTextField findTextField; private JTextField replaceTextField; private JButton findNextButton; private JButton replaceFindButton; private JButton replaceButton; private JButton replaceAllButton; private JButton closeButton; private JCheckBox caseSensitiveCheckBox; private JCheckBox wholeWordCheckBox; private JRadioButton regexButton; private JRadioButton wildCardsButton; private JRadioButton literalButton; private JLabel findLabel; private JLabel replaceLabel; private boolean initLoc; private final RobocodeEditor editor; public FindReplaceDialog(RobocodeEditor owner) { super(owner, false); editor = owner; JPanel bigPanel = new JPanel(); bigPanel.setLayout(new BoxLayout(bigPanel, BoxLayout.X_AXIS)); JPanel leftPanel = new JPanel(); leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS)); JPanel findReplacePanel = new JPanel(); findReplacePanel.setLayout(new BoxLayout(findReplacePanel, BoxLayout.X_AXIS)); JPanel labelsPanel = new JPanel(); labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.Y_AXIS)); labelsPanel.add(getFindLabel()); labelsPanel.add(getReplaceLabel()); findReplacePanel.add(labelsPanel); JPanel fieldsPanel = new JPanel(); fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.Y_AXIS)); fieldsPanel.add(getFindTextField()); fieldsPanel.add(getReplaceTextField()); findReplacePanel.add(fieldsPanel); leftPanel.add(findReplacePanel); JPanel optionsPanel = new JPanel(); optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.X_AXIS)); JPanel checkboxPanel = new JPanel(); checkboxPanel.setLayout(new BoxLayout(checkboxPanel, BoxLayout.Y_AXIS)); checkboxPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Options")); checkboxPanel.add(getCaseSensitiveCheckBox()); checkboxPanel.add(getWholeWordCheckBox()); checkboxPanel.setAlignmentY(TOP_ALIGNMENT); optionsPanel.add(checkboxPanel); JPanel radioPanel = new JPanel(); radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.Y_AXIS)); radioPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Use:")); radioPanel.add(getLiteralButton()); radioPanel.add(getWildCardsButton()); radioPanel.add(getRegexButton()); radioPanel.setAlignmentY(TOP_ALIGNMENT); ButtonGroup buttonGroup = new ButtonGroup(); buttonGroup.add(getLiteralButton()); buttonGroup.add(getWildCardsButton()); buttonGroup.add(getRegexButton()); optionsPanel.add(radioPanel); leftPanel.add(optionsPanel); leftPanel.setAlignmentY(TOP_ALIGNMENT); bigPanel.add(leftPanel); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); buttonPanel.add(getFindNextButton()); buttonPanel.add(getReplaceFindButton()); buttonPanel.add(getReplaceButton()); buttonPanel.add(getReplaceAllButton()); buttonPanel.add(getCloseButton()); buttonPanel.setAlignmentY(TOP_ALIGNMENT); bigPanel.add(buttonPanel); setContentPane(bigPanel); } public void showDialog(boolean showReplace) { getReplaceLabel().setVisible(showReplace); getReplaceTextField().setVisible(showReplace); getReplaceButton().setVisible(showReplace); getReplaceAllButton().setVisible(showReplace); if (showReplace) { setTitle("Replace"); getRootPane().setDefaultButton(getReplaceButton()); getReplaceFindButton().setText("Find..."); getReplaceFindButton().setMnemonic('d'); getReplaceFindButton().setDisplayedMnemonicIndex(3); } else { setTitle("Find"); getRootPane().setDefaultButton(getFindNextButton()); getReplaceFindButton().setText("Replace..."); getReplaceFindButton().setMnemonic('R'); getReplaceFindButton().setDisplayedMnemonicIndex(0); } pack(); if (!initLoc && editor != null) { Rectangle bounds = editor.getBounds(); Dimension size = getSize(); setLocation((int) (bounds.getX() + (bounds.getWidth() - size.getWidth()) / 2), (int) (bounds.getY() + (bounds.getHeight() - size.getHeight()) / 2)); initLoc = true; } // Bugfix [2664844] - Editor: Find (set cursor position) getFindTextField().requestFocus(); setVisible(true); } public JLabel getFindLabel() { if (findLabel == null) { findLabel = new JLabel(); findLabel.setText("Find:"); findLabel.setDisplayedMnemonicIndex(3); } return findLabel; } public JLabel getReplaceLabel() { if (replaceLabel == null) { replaceLabel = new JLabel(); replaceLabel.setText("Replace:"); replaceLabel.setDisplayedMnemonicIndex(3); } return replaceLabel; } public JTextField getFindTextField() { if (findTextField == null) { findTextField = new JTextField(); findTextField.setFocusAccelerator('n'); findTextField.addActionListener(this); } return findTextField; } public JTextField getReplaceTextField() { if (replaceTextField == null) { replaceTextField = new JTextField(); replaceTextField.setFocusAccelerator('p'); replaceTextField.addActionListener(this); } return replaceTextField; } public JButton getFindNextButton() { if (findNextButton == null) { findNextButton = new JButton(); findNextButton.setText("Find Next"); findNextButton.setMnemonic('F'); findNextButton.setDefaultCapable(true); findNextButton.addActionListener(this); } return findNextButton; } public JButton getReplaceFindButton() { if (replaceFindButton == null) { replaceFindButton = new JButton("Replace..."); replaceFindButton.setMnemonic('R'); replaceFindButton.addActionListener(this); } return replaceFindButton; } public JButton getReplaceButton() { if (replaceButton == null) { replaceButton = new JButton(); replaceButton.setText("Replace"); replaceButton.setMnemonic('R'); replaceButton.setDefaultCapable(true); replaceButton.addActionListener(this); } return replaceButton; } public JButton getReplaceAllButton() { if (replaceAllButton == null) { replaceAllButton = new JButton(); replaceAllButton.setText("Replace All"); replaceAllButton.setMnemonic('A'); replaceAllButton.setDisplayedMnemonicIndex(8); replaceAllButton.addActionListener(this); } return replaceAllButton; } public JButton getCloseButton() { if (closeButton == null) { closeButton = new JButton(); closeButton.setText("Close"); closeButton.setMnemonic('C'); closeButton.addActionListener(this); } return closeButton; } public JCheckBox getCaseSensitiveCheckBox() { if (caseSensitiveCheckBox == null) { caseSensitiveCheckBox = new JCheckBox(); caseSensitiveCheckBox.setText("Case Sensitive"); caseSensitiveCheckBox.setMnemonic('v'); caseSensitiveCheckBox.setDisplayedMnemonicIndex(12); caseSensitiveCheckBox.addActionListener(this); } return caseSensitiveCheckBox; } public JCheckBox getWholeWordCheckBox() { if (wholeWordCheckBox == null) { wholeWordCheckBox = new JCheckBox(); wholeWordCheckBox.setText("Whole Words Only"); wholeWordCheckBox.setMnemonic('W'); wholeWordCheckBox.addActionListener(this); } return wholeWordCheckBox; } public JRadioButton getLiteralButton() { if (literalButton == null) { literalButton = new JRadioButton(); literalButton.setText("Literal"); literalButton.setMnemonic('L'); literalButton.setSelected(true); literalButton.addActionListener(this); } return literalButton; } public JRadioButton getWildCardsButton() { if (wildCardsButton == null) { wildCardsButton = new JRadioButton(); wildCardsButton.setText("Wild Cards"); wildCardsButton.setMnemonic('i'); wildCardsButton.setDisplayedMnemonicIndex(1); wildCardsButton.addActionListener(this); } return wildCardsButton; } public JRadioButton getRegexButton() { if (regexButton == null) { regexButton = new JRadioButton(); regexButton.setText("Regular Expressions"); regexButton.setMnemonic('x'); regexButton.setDisplayedMnemonicIndex(9); regexButton.addActionListener(this); } return regexButton; } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == getFindNextButton()) { findNext(); } else if (source == getReplaceButton()) { doReplacement(); findNext(); } else if (source == getReplaceAllButton()) { doReplaceAll(); } else if (source == getCloseButton()) { setVisible(false); } else if (source == getReplaceFindButton()) { showDialog(!getReplaceButton().isVisible()); } else if (source instanceof JTextField) { getRootPane().getDefaultButton().doClick(); } } private Pattern getCurrentPattern() { String pattern = getFindTextField().getText(); int flags = Pattern.DOTALL; if (!getRegexButton().isSelected()) { StringBuffer newpattern = new StringBuffer(); // 'quote' the pattern for (int i = 0; i < pattern.length(); i++) { if ("\\[]^$&|().*+?{}".indexOf(pattern.charAt(i)) >= 0) { newpattern.append('\\'); } newpattern.append(pattern.charAt(i)); } pattern = newpattern.toString(); // make "*" .* and "?" . if (getWildCardsButton().isSelected()) { pattern = pattern.replaceAll("\\\\\\*", ".+?"); pattern = pattern.replaceAll("\\\\\\?", "."); } } if (!getCaseSensitiveCheckBox().isSelected()) { flags |= Pattern.CASE_INSENSITIVE; } if (getWholeWordCheckBox().isSelected()) { pattern = "\\b" + pattern + "\\b"; } return Pattern.compile(pattern, flags); } public void findNext() { EditWindow currentWindow = editor.getActiveWindow(); if (currentWindow == null || getFindTextField().getText().length() == 0) { // launch error dialog? return; } Pattern p = getCurrentPattern(); JEditorPane editorPane = currentWindow.getEditorPane(); // for some reason, getText() trims off \r but the indexes in // the editor pane don't. String text = editorPane.getText().replaceAll("\\r", ""); Matcher m = p.matcher(text); int index = editorPane.getSelectionEnd(); if (!(m.find(index) || m.find())) { return; } editorPane.setSelectionStart(m.start()); editorPane.setSelectionEnd(m.end()); } public void doReplacement() { EditWindow currentWindow = editor.getActiveWindow(); if (currentWindow == null || getFindTextField().getText().length() == 0) { // launch error dialog? return; } JEditorPane editorPane = currentWindow.getEditorPane(); String text = editorPane.getSelectedText(); if (text == null) { // no selection return; } Matcher m = getCurrentPattern().matcher(text); if (m.matches()) { String replacement = getReplaceTextField().getText(); if (getRegexButton().isSelected()) { replacement = m.replaceFirst(replacement); } editorPane.replaceSelection(replacement); } } public void doReplaceAll() { EditWindow currentWindow = editor.getActiveWindow(); if (currentWindow == null || getFindTextField().getText().length() == 0) { // launch error dialog? return; } JEditorPane editorPane = currentWindow.getEditorPane(); String text = editorPane.getText(); String replacement = getReplaceTextField().getText(); editorPane.setText(getCurrentPattern().matcher(text).replaceAll(replacement)); } }