package com.vistatec.ocelot.findrep; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTextField; import javax.swing.SwingConstants; /** * Dialog providing graphical tools for performing the find and replace * functionality. */ public class FindReplaceDialog extends JDialog implements ActionListener, ItemListener { /** The serial version UID. */ private static final long serialVersionUID = 1L; /** The dialog width. */ private static final int WIDTH = 450; /** The dialog height. */ private static final int HEIGHT = 300; /** The buttons width. */ private static final int BTN_WIDTH = 100; /** The buttons height. */ private static final int BTN_HEIGHT = 25; /** The label width. */ private static final int LBL_WIDTH = 100; /** The label height. */ private static final int LBL_HEIGHT = 25; /** The text fields width. */ private static final int TXT_WIDTH = 300; /** The text fields height. */ private static final int TXT_HEIGHT = 25; /** The Settings panel width. */ private static final int SETTING_PANELS_WIDTH = 135; /** The settings panel height. */ private static final int SETTING_PANELS_HEIGHT = 100; /** The text displaying the number of found occurrences. */ private static final String OCCUR_NUM_LBL_TEXT = "Found $$$ occurrences. "; /** The string to be replaced with the actual number of occurrences. */ private static final String OCCUR_NUM_REPLACE_STRING = "$$$"; /** The find next button. */ private JButton btnFindNext; /** The replace button. */ private JButton btnReplace; /** The replace all button. */ private JButton btnReplaceAll; /** The find all button. */ private JButton btnFindAll; /** The close button. */ private JButton btnClose; /** The find text field. */ private JTextField txtFind; /** The replace text field. */ private JTextField txtReplace; /** The case sensitive check box. */ private JCheckBox ckCaseSensitive; /** The whole word check box. */ private JCheckBox ckWholeWord; /** The wrap search check box. */ private JCheckBox ckWrapSearch; /** The source radio button. */ private JRadioButton rbtnSource; /** The target radio button. */ private JRadioButton rbtnTarget; /** The up radio button. */ private JRadioButton rbtnUp; /** The down radio button. */ private JRadioButton rbtnDown; /** The string not found label. */ private JLabel lblStrNotFound; /** The end of document reached label. */ private JLabel lblEndOfDoc; /** The beginning of document reached label. */ private JLabel lblBeginOfDoc; /** The label displaying the number of found occurrences. */ private JLabel lblOccNum; /** The replace label. */ private JLabel lblReplace; /** The controller. */ private FindAndReplaceController controller; /** * Constructor. * * @param owner * the owner window * @param controller * the controller */ public FindReplaceDialog(Window owner, FindAndReplaceController controller) { super(owner); setModal(false); this.controller = controller; makeFrame(); } /** * Makes the frame. */ private void makeFrame() { setResizable(false); setSize(new Dimension(WIDTH, HEIGHT)); setPreferredSize(new Dimension(WIDTH, HEIGHT)); setTitle("Find/Replace"); add(getMainComponent(), BorderLayout.CENTER); add(getBottomComponent(), BorderLayout.SOUTH); setLocationRelativeTo(null); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { controller.closeDialog(); } }); rbtnSource.setSelected(true); } /** * Gets the component to be displayed at the bottom of the dialog. * * @return the component to be displayed at the bottom of the dialog. */ private Component getBottomComponent() { btnFindNext = new JButton("Find Next"); configButton(btnFindNext); btnReplace = new JButton("Replace"); configButton(btnReplace); btnReplaceAll = new JButton("Replace All"); configButton(btnReplaceAll); btnFindAll = new JButton("Find All"); configButton(btnFindAll); btnClose = new JButton("Close"); configButton(btnClose); lblStrNotFound = new JLabel("String not found."); lblStrNotFound.setForeground(Color.red); Color darkgreen = new Color(0, 153, 0); lblEndOfDoc = new JLabel("End of document reached."); lblEndOfDoc.setForeground(darkgreen); lblBeginOfDoc = new JLabel("Beginning of document reached."); lblBeginOfDoc.setForeground(darkgreen); lblOccNum = new JLabel(); lblOccNum.setForeground(darkgreen); JPanel topPanel = new JPanel(); topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS)); topPanel.add(Box.createHorizontalStrut(16)); topPanel.add(btnFindNext); topPanel.add(Box.createHorizontalStrut(10)); // topPanel.add(Box.createHorizontalGlue()); // topPanel.add(btnFindAll); // topPanel.add(Box.createHorizontalStrut(10)); topPanel.add(btnReplace); topPanel.add(Box.createHorizontalStrut(10)); topPanel.add(btnReplaceAll); topPanel.add(Box.createHorizontalGlue()); topPanel.add(Box.createHorizontalStrut(16)); JPanel bottomPanel = new JPanel(); bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS)); bottomPanel.add(Box.createHorizontalStrut(5)); bottomPanel.add(lblStrNotFound); bottomPanel.add(lblOccNum); bottomPanel.add(lblBeginOfDoc); bottomPanel.add(lblEndOfDoc); bottomPanel.add(Box.createHorizontalGlue()); bottomPanel.add(btnClose); bottomPanel.add(Box.createHorizontalStrut(16)); lblStrNotFound.setVisible(false); lblEndOfDoc.setVisible(false); lblBeginOfDoc.setVisible(false); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.add(topPanel); panel.add(bottomPanel); return panel; } /** * Configures a button. * * @param btn * the button. */ private void configButton(JButton btn) { btn.setSize(new Dimension(BTN_WIDTH, BTN_HEIGHT)); btn.setPreferredSize(new Dimension(BTN_WIDTH, BTN_HEIGHT)); btn.addActionListener(this); } /** * Gets the component to be displayed in the center of the dialog. * * @return the component to be displayed in the center of the dialog. */ private Component getMainComponent() { JPanel panel = new JPanel(); panel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); JLabel lblFind = new JLabel("Find:"); configLabel(lblFind); lblReplace = new JLabel("Replace with:"); configLabel(lblReplace); txtFind = new JTextField(); configTxt(txtFind); txtReplace = new JTextField(); configTxt(txtReplace); panel.add(lblFind); panel.add(txtFind); panel.add(lblReplace); panel.add(txtReplace); panel.add(getSettingsPanel()); return panel; } /** * Gets the settings panel. * * @return the settings panel. */ private Component getSettingsPanel() { JPanel settingsPanel = new JPanel(); settingsPanel.add(getOptionsPanel()); settingsPanel.add(getDirectionPanel()); settingsPanel.add(getScopePanel()); return settingsPanel; } /** * Gets the options panel. * * @return the options panel. */ private Component getOptionsPanel() { JPanel optionsPanel = new JPanel(); optionsPanel.setPreferredSize(new Dimension(SETTING_PANELS_WIDTH, SETTING_PANELS_HEIGHT)); optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS)); optionsPanel.setBorder(BorderFactory.createTitledBorder("Options")); ckCaseSensitive = new JCheckBox("Match Case"); ckCaseSensitive.addItemListener(this); ckWholeWord = new JCheckBox("Whole Word"); ckWholeWord.addItemListener(this); ckWrapSearch = new JCheckBox("Wrap Search"); ckWrapSearch.addItemListener(this); optionsPanel.add(ckCaseSensitive); optionsPanel.add(ckWholeWord); optionsPanel.add(ckWrapSearch); return optionsPanel; } /** * Gets the direction panel. * * @return the direction panel. */ private Component getDirectionPanel() { JPanel directionPanel = new JPanel(); directionPanel.setPreferredSize(new Dimension(SETTING_PANELS_WIDTH, SETTING_PANELS_HEIGHT)); directionPanel .setLayout(new BoxLayout(directionPanel, BoxLayout.Y_AXIS)); directionPanel.setBorder(BorderFactory.createTitledBorder("Direction")); rbtnDown = new JRadioButton("Down"); rbtnDown.addItemListener(this); rbtnUp = new JRadioButton("Up"); rbtnUp.addItemListener(this); rbtnDown.setSelected(true); ButtonGroup group = new ButtonGroup(); group.add(rbtnDown); group.add(rbtnUp); directionPanel.add(rbtnDown); directionPanel.add(rbtnUp); return directionPanel; } /** * Gets the scope panel. * * @return the scope panel. */ private Component getScopePanel() { JPanel scopePanel = new JPanel(); scopePanel.setPreferredSize(new Dimension(SETTING_PANELS_WIDTH, SETTING_PANELS_HEIGHT)); scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS)); scopePanel.setBorder(BorderFactory.createTitledBorder("Scope")); rbtnSource = new JRadioButton("Source"); rbtnSource.addItemListener(this); rbtnTarget = new JRadioButton("Target"); rbtnTarget.addItemListener(this); ButtonGroup group = new ButtonGroup(); group.add(rbtnSource); group.add(rbtnTarget); scopePanel.add(rbtnSource); scopePanel.add(rbtnTarget); return scopePanel; } /** * Configures a label. * * @param lbl * the label */ private void configLabel(JLabel lbl) { lbl.setHorizontalAlignment(SwingConstants.RIGHT); lbl.setSize(new Dimension(LBL_WIDTH, LBL_HEIGHT)); lbl.setPreferredSize(new Dimension(LBL_WIDTH, LBL_HEIGHT)); } /** * Configures a text field. * * @param txt * the text field. */ private void configTxt(JTextField txt) { txt.setPreferredSize(new Dimension(TXT_WIDTH, TXT_HEIGHT)); txt.setSize(new Dimension(TXT_WIDTH, TXT_HEIGHT)); } /** * Opens the dialog. */ public void open() { setVisible(true); } /* * (non-Javadoc) * * @see * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ @Override public void actionPerformed(ActionEvent e) { if (e.getSource().equals(btnClose)) { close(); } else if (e.getSource().equals(btnFindNext)) { findNext(); } else if (e.getSource().equals(btnReplace)) { replace(); } else if (e.getSource().equals(btnReplaceAll)) { replaceAll(); // } else if (e.getSource().equals(btnFindAll)) { // findAll(); } } /** * Sets the search result and the proper label is displayed. * * @param result * the result. */ public void setResult(int result) { if (result == FindAndReplaceController.RESULT_FOUND) { lblBeginOfDoc.setVisible(false); lblEndOfDoc.setVisible(false); lblStrNotFound.setVisible(false); } else if (result == FindAndReplaceController.RESULT_NOT_FOUND) { lblBeginOfDoc.setVisible(false); lblEndOfDoc.setVisible(false); lblStrNotFound.setVisible(true); lblOccNum.setVisible(false); } else if (result == FindAndReplaceController.RESULT_END_OF_DOC_REACHED) { if (rbtnDown.isSelected()) { lblBeginOfDoc.setVisible(false); lblEndOfDoc.setVisible(true); } else { lblBeginOfDoc.setVisible(true); lblEndOfDoc.setVisible(false); } lblStrNotFound.setVisible(false); } } /** * Displays the number of found occurrences. * * @param occurNum * the number of occurrences. */ public void displayOccurrenceNum(int occurNum) { lblOccNum.setText(OCCUR_NUM_LBL_TEXT.replace(OCCUR_NUM_REPLACE_STRING, String.valueOf(occurNum))); setResult(FindAndReplaceController.RESULT_FOUND); lblOccNum.setVisible(true); } /** * Hides the number of occurrences. */ public void hideOccNumber() { lblOccNum.setVisible(false); lblBeginOfDoc.setVisible(false); lblEndOfDoc.setVisible(false); } /** * Replaces all instances. */ private void replaceAll() { controller.replaceAll(txtReplace.getText()); } /** * Replaces the last found string with the text contained in the replace * text field. */ private void replace() { controller.replace(txtReplace.getText()); } /** * Finds the next occurrence of the text contained in the find text field. */ private void findNext() { if (!txtFind.getText().isEmpty()) { controller.findNext(txtFind.getText()); } } /** * Closes the dialog. */ private void close() { controller.closeDialog(); setVisible(false); } /* * (non-Javadoc) * * @see * java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent) */ @Override public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { if (e.getSource().equals(rbtnSource)) { enableReplaceFunctionality(false); controller.setSourceScope(); } else if (e.getSource().equals(rbtnTarget)) { enableReplaceFunctionality(true); controller.setTargetScope(); } else if (e.getSource().equals(rbtnDown)) { controller.setSearchDirectionDown(); } else if (e.getSource().equals(rbtnUp)) { controller.setSearchDirectionUp(); } } if (e.getSource().equals(ckCaseSensitive)) { controller.setCaseSensitive(ckCaseSensitive.isSelected()); } else if (e.getSource().equals(ckWholeWord)) { controller.setWholeWord(ckWholeWord.isSelected()); } else if (e.getSource().equals(ckWrapSearch)) { controller.setWrapSearch(ckWrapSearch.isSelected()); } } /** * Enables the replace functionality. * * @param enable * boolean stating if the replace functionality is enabled. */ private void enableReplaceFunctionality(boolean enable) { txtReplace.setEnabled(enable); btnReplace.setEnabled(enable); btnReplaceAll.setEnabled(enable); lblReplace.setEnabled(enable); } /** * Gets the selected scope. * * @return the selected scope. */ public int getSelectedScope() { if (rbtnSource.isSelected()) { return WordFinder.SCOPE_SOURCE; } else { return WordFinder.SCOPE_TARGET; } } }