com.intuit.tank.tools.debugger.FindReplaceDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.intuit.tank.tools.debugger.FindReplaceDialog.java

Source

package com.intuit.tank.tools.debugger;

/*
 * #%L
 * Intuit Tank Agent Debugger
 * %%
 * Copyright (C) 2011 - 2015 Intuit Inc.
 * %%
 * 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://www.eclipse.org/legal/epl-v10.html
 * #L%
 */

import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

import org.apache.commons.lang.StringUtils;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;

public class FindReplaceDialog extends JDialog implements ActionListener {
    private static final long serialVersionUID = 1L;

    public enum DialogType {
        SEARCH, // Defines a search only dialog
        REPLACE // Defines a search and replace dialog
    }

    // Private declarations
    private AgentDebuggerFrame parent;
    private JComboBox cbSearch;
    private JComboBox cbReplace;
    private JTextField tfSearchEditor;
    private JTextField tfReplaceEditor;
    private JButton btnFind;
    private JButton btnReplace;
    private JButton btnReplaceAll;
    private JButton btnCancel;
    private JCheckBox checkboxMatchCase;
    private JCheckBox checkboxRegexp;
    private JCheckBox checkboxWrap;
    private int currentLine;
    private int initialLine;
    private int initialRunningStep;

    /**
     * Constructs a new find dialog according to the specified type of dialog requested. The dialog can be either a FIND
     * dialog, either a REPLACE dialog. In both cases, components displayed remain the sames, but the ones specific to
     * replace feature are grayed out.
     * 
     * @param parent
     *            The window holder
     * @param type
     *            The type of the dialog: FindReplace.FIND or FindReplace.REPLACE
     * @param modal
     *            Displays dialog as a modal window if true
     */

    public FindReplaceDialog(AgentDebuggerFrame parent, DialogType type) {
        super(parent, type == DialogType.REPLACE ? "Replace" : "Find", true);
        this.parent = parent;

        cbSearch = new JComboBox();
        cbSearch.setEditable(true);
        cbReplace = new JComboBox();
        cbReplace.setEditable(true);
        KeyHandler handler = new KeyHandler();
        tfSearchEditor = (JTextField) cbSearch.getEditor().getEditorComponent();
        tfSearchEditor.addKeyListener(handler);
        tfReplaceEditor = (JTextField) cbReplace.getEditor().getEditorComponent();
        tfReplaceEditor.addKeyListener(handler);

        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints constraints = new GridBagConstraints();
        getContentPane().setLayout(gridbag);
        ((JPanel) getContentPane()).setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        int gridX = 0;
        int gridY = 0;
        JLabel findLabel = new JLabel("Find");
        buildConstraints(constraints, gridX, gridY, 1, 1, 0, 0);
        constraints.anchor = GridBagConstraints.WEST;
        gridbag.setConstraints(findLabel, constraints);
        getContentPane().add(findLabel);
        gridX++;

        buildConstraints(constraints, gridX, gridY, 1, 1, 100, 0);
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.anchor = GridBagConstraints.CENTER;
        gridbag.setConstraints(cbSearch, constraints);
        getContentPane().add(cbSearch);
        gridX++;

        btnFind = new JButton("Find");
        btnFind.setToolTipText("Find text in scripts");
        btnFind.setMnemonic('F');
        btnFind.addActionListener(this);
        buildConstraints(constraints, gridX, gridY, 1, 1, 0, 0);
        constraints.anchor = GridBagConstraints.CENTER;
        gridbag.setConstraints(btnFind, constraints);
        getContentPane().add(btnFind);
        getRootPane().setDefaultButton(btnFind);
        gridX++;

        btnCancel = new JButton("Cancel");
        btnCancel.setMnemonic('C');
        btnCancel.addActionListener(this);
        buildConstraints(constraints, gridX, gridY, 1, 1, 0, 0);
        constraints.anchor = GridBagConstraints.CENTER;
        gridbag.setConstraints(btnCancel, constraints);
        getContentPane().add(btnCancel);
        gridY++;
        gridX = 0;
        if (type == DialogType.REPLACE) {
            JLabel replaceLabel = new JLabel("Replace");
            buildConstraints(constraints, gridX, gridY, 1, 1, 0, 0);
            constraints.anchor = GridBagConstraints.WEST;
            gridbag.setConstraints(replaceLabel, constraints);
            getContentPane().add(replaceLabel);
            gridX++;

            buildConstraints(constraints, gridX, gridY, 1, 1, 100, 0);
            constraints.fill = GridBagConstraints.HORIZONTAL;
            constraints.anchor = GridBagConstraints.CENTER;
            gridbag.setConstraints(cbReplace, constraints);
            getContentPane().add(cbReplace);
            gridX++;

            btnReplace = new JButton("Replace");
            btnReplace.setToolTipText("REplace in script");
            btnReplace.setMnemonic('R');
            btnReplace.addActionListener(this);
            buildConstraints(constraints, gridX, gridY, 1, 1, 0, 0);
            constraints.anchor = GridBagConstraints.CENTER;
            gridbag.setConstraints(btnReplace, constraints);
            getContentPane().add(btnReplace);
            gridX++;

            btnReplaceAll = new JButton("Replace All");
            btnReplaceAll.addActionListener(this);
            buildConstraints(constraints, gridX, gridY, 1, 1, 0, 0);
            constraints.anchor = GridBagConstraints.CENTER;
            gridbag.setConstraints(btnReplaceAll, constraints);
            getContentPane().add(btnReplaceAll);
            btnReplace.addKeyListener(handler);
            btnReplaceAll.addKeyListener(handler);
            gridY++;
            gridX = 0;
        }

        TitledBorder border = new TitledBorder("Options");
        JPanel panel = new JPanel(new GridLayout(1, 4));
        panel.setBorder(border);
        checkboxWrap = new JCheckBox("Wrap Search");
        panel.add(checkboxWrap);

        checkboxMatchCase = new JCheckBox("Case sensitive");
        panel.add(checkboxMatchCase);

        checkboxRegexp = new JCheckBox("Regular expressions");
        panel.add(checkboxRegexp);

        buildConstraints(constraints, gridX, gridY, 4, 1, 100, 100);
        constraints.anchor = GridBagConstraints.WEST;
        gridbag.setConstraints(panel, constraints);
        getContentPane().add(panel);

        FontMetrics fm = getFontMetrics(getFont());
        cbSearch.setPreferredSize(new Dimension(18 * fm.charWidth('m'), (int) cbSearch.getPreferredSize().height));
        cbReplace
                .setPreferredSize(new Dimension(18 * fm.charWidth('m'), (int) cbReplace.getPreferredSize().height));

        pack();
        // setResizable(false);
        WindowUtil.centerOnParent(this);

        // patch by MJB 8/1/2002
        btnFind.addKeyListener(handler);

        btnCancel.addKeyListener(handler);
        checkboxMatchCase.addKeyListener(handler);
        checkboxRegexp.addKeyListener(handler);

    }

    @Override
    public void setVisible(boolean b) {
        tfSearchEditor.setText("");
        if (tfReplaceEditor != null) {
            tfReplaceEditor.setText("");
        }
        RSyntaxTextArea ta = parent.getScriptEditorTA();
        if (b) {
            currentLine = ta.getCaretLineNumber();
            initialRunningStep = parent.getCurrentRunningStep();
            initialLine = ta.getCaretLineNumber();
            tfSearchEditor.requestFocusInWindow();
        } else {
            // if (initialRunningStep >= 0 && initialRunningStep < ta.getLineCount() -1) {
            // ta.setActiveLineRange(initialRunningStep + 1, initialRunningStep + 1);
            // } else {
            // ta.setActiveLineRange(-1, -1);
            // }
            // parent.fireStepChanged(initialRunningStep);
            // ta.setCurrentLine(initialLine);
            // parent.repaint();
        }
        super.setVisible(b);
    }

    // Catch the action performed and then look for its source
    // According to the source object we call appropriate methods

    public void actionPerformed(ActionEvent evt) {
        Object source = evt.getSource();
        if (source == btnCancel) {
            setVisible(false);
        } else if (source == btnFind) {
            doFind();
        } else if (source == btnReplace) {
            doReplace();
        } else if (source == btnReplaceAll) {
            doReplaceAll();
        }
    }

    // replace all the occurences of search pattern by
    // the replace one. If 'All Files' is checked, this is
    // done in all the opened file in the component 'parent'

    private void doReplaceAll() {
        addReplaceHistory();
        addSearchHistory();
        // try {
        // JextTextArea textArea = parent.getTextArea();
        // setSettings();
        // if (Search.replaceAll(textArea, 0, textArea.getLength()) == 0) {
        // Utilities.beep();
        // }
        //
        // } catch (Exception e) {
        // // nothing
        // } finally {
        // Utilities.setCursorOnWait(this, false);
        // }
    }

    // replaces specified search pattern by the replace one.
    // this is done only if a match is found.

    private void doReplace() {
        addReplaceHistory();
        addSearchHistory();
        //
        // try {
        //
        // JextTextArea textArea = parent.getTextArea();
        // setSettings();
        //
        // if (!Search.replace(textArea))
        // {
        // Utilities.beep();
        // } else
        // find(textArea);
        //
        // } catch (Exception e) {
        // // nothing
        // } finally {
        // Utilities.setCursorOnWait(this, false);
        // }
    }

    // finds the next occurence of current search pattern
    // the search is done in current text area

    private void doFind() {
        addSearchHistory();
        find(parent.getScriptEditorTA());
    }

    // finds the next occurence of the search pattern in a
    // a given text area. if match is not found, and if user
    // don't ask to start over from beginning, then the method
    // calls itself by specifying next opened text area.

    private void find(RSyntaxTextArea textArea) {

        try {
            int offset = currentLine < textArea.getLineCount() ? textArea.getLineStartOffset(currentLine) : 0;
            String searchTerm = tfSearchEditor.getText();
            String text = textArea.getText();
            int foundIndex = -1;
            int flags = (checkboxRegexp.isSelected() ? 0 : Pattern.LITERAL)
                    | (checkboxMatchCase.isSelected() ? 0 : Pattern.CASE_INSENSITIVE);
            Pattern p = Pattern.compile(searchTerm, flags);
            Matcher matcher = p.matcher(text);
            matcher.region(offset, text.length());
            if (matcher.find()) {
                foundIndex = matcher.start();
            } else if (checkboxWrap.isSelected() && offset > 0) {
                matcher.region(0, offset);
                if (matcher.find()) {
                    foundIndex = matcher.start();
                }
            }
            if (foundIndex != -1) {
                int lineOfOffset = textArea.getLineOfOffset(foundIndex);
                // textArea.setActiveLineRange(lineOfOffset, lineOfOffset);
                textArea.setCurrentLine(lineOfOffset);
                // textArea.setCaretPosition(foundIndex + searchTerm.length());
                parent.repaint();
                parent.fireStepChanged(lineOfOffset);
                currentLine = lineOfOffset + 1;
            } else {
                JOptionPane.showMessageDialog(parent, "Search String not found.");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * adds current search pattern in the search history list
     */
    private void addSearchHistory() {
        addSearchHistory(tfSearchEditor.getText());
    }

    /**
     * adds a pattern in the search history list
     * 
     * @param c
     *            the pattern to be added
     */
    private void addSearchHistory(String c) {
        if (StringUtils.isBlank(c)) {
            return;
        }
        for (int i = 0; i < cbSearch.getItemCount(); i++) {
            if (((String) cbSearch.getItemAt(i)).equals(c)) {
                return;
            }
        }
        cbSearch.insertItemAt(c, 0);
        if (cbSearch.getItemCount() > 25) {
            for (int i = 25; i < cbSearch.getItemCount();)
                cbSearch.removeItemAt(i);
        }
        tfSearchEditor.setText((String) cbSearch.getItemAt(0));
    }

    /**
     * adds current replace pattern in the replace history list
     */
    private void addReplaceHistory() {
        addReplaceHistory(tfReplaceEditor.getText());
    }

    /**
     * adds a pattern in the replace history list
     * 
     * @param c
     *            the pattern to be added
     */
    private void addReplaceHistory(String c) {
        if (StringUtils.isBlank(c)) {
            return;
        }

        for (int i = 0; i < cbReplace.getItemCount(); i++) {
            if (((String) cbReplace.getItemAt(i)).equals(c)) {
                return;
            }
        }

        cbReplace.insertItemAt(c, 0);
        if (cbReplace.getItemCount() > 25) {
            for (int i = 25; i < cbReplace.getItemCount();)
                cbReplace.removeItemAt(i);
        }

        tfReplaceEditor.setText((String) cbReplace.getItemAt(0));
    }

    private void buildConstraints(GridBagConstraints agbc, int agx, int agy, int agw, int agh, int awx, int awy) {
        agbc.gridx = agx;
        agbc.gridy = agy;
        agbc.gridwidth = agw;
        agbc.gridheight = agh;
        agbc.weightx = awx;
        agbc.weighty = awy;
        agbc.insets = new Insets(2, 2, 2, 2);
    }

    class KeyHandler extends KeyAdapter {
        public void keyPressed(KeyEvent evt) {
            switch (evt.getKeyCode()) {
            case KeyEvent.VK_ENTER:
                if (evt.getSource() == tfSearchEditor) {
                    doFind();
                } else if (evt.getSource() == tfReplaceEditor) {
                    doReplace();
                }
                break;
            case KeyEvent.VK_ESCAPE:
                setVisible(false);
                break;
            }
        }
    }

}