diff --git a/app/src/cc/arduino/view/findreplace/FindReplace.form b/app/src/cc/arduino/view/findreplace/FindReplace.form
new file mode 100644
index 000000000..3c89f59b0
--- /dev/null
+++ b/app/src/cc/arduino/view/findreplace/FindReplace.form
@@ -0,0 +1,196 @@
+
+
+
diff --git a/app/src/cc/arduino/view/findreplace/FindReplace.java b/app/src/cc/arduino/view/findreplace/FindReplace.java
new file mode 100644
index 000000000..881774e24
--- /dev/null
+++ b/app/src/cc/arduino/view/findreplace/FindReplace.java
@@ -0,0 +1,460 @@
+/*
+ * This file is part of Arduino.
+ *
+ * Copyright 2015 Arduino LLC (http://www.arduino.cc/)
+ *
+ * Arduino is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction. Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License. This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ */
+
+package cc.arduino.view.findreplace;
+
+import processing.app.Base;
+import processing.app.Editor;
+import processing.app.Sketch;
+import processing.app.helpers.OSUtils;
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.HashMap;
+import java.util.Map;
+
+import static processing.app.I18n._;
+
+public class FindReplace extends javax.swing.JFrame {
+
+ private static final String FIND_TEXT = "findText";
+ private static final String REPLACE_TEXT = "replaceText";
+ private static final String IGNORE_CASE = "ignoreCase";
+ private static final String SEARCH_ALL_FILES = "searchAllFiles";
+ private static final String WRAP_AROUND = "wrapAround";
+
+ private final Editor editor;
+
+ public FindReplace(Editor editor, Map state) {
+ this.editor = editor;
+
+ initComponents();
+
+ if (OSUtils.isMacOS()) {
+ buttonsContainer.removeAll();
+ buttonsContainer.add(replaceAllButton);
+ buttonsContainer.add(replaceButton);
+ buttonsContainer.add(replaceFindButton);
+ buttonsContainer.add(previousButton);
+ buttonsContainer.add(findButton);
+ }
+
+ getRootPane().setDefaultButton(findButton);
+
+ Base.registerWindowCloseKeys(getRootPane(), new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ setVisible(false);
+ Base.FIND_DIALOG_STATE = findDialogState();
+ }
+ });
+
+ Base.setIcon(this);
+
+ addWindowListener(new WindowAdapter() {
+ public void windowActivated(WindowEvent e) {
+ findField.requestFocusInWindow();
+ findField.selectAll();
+ }
+ });
+
+ restoreFindDialogState(state);
+ }
+
+ private Map findDialogState() {
+ Map state = new HashMap();
+ state.put(FIND_TEXT, findField.getText());
+ state.put(REPLACE_TEXT, replaceField.getText());
+ state.put(IGNORE_CASE, ignoreCaseBox.isSelected());
+ state.put(WRAP_AROUND, wrapAroundBox.isSelected());
+ state.put(SEARCH_ALL_FILES, searchAllFilesBox.isSelected());
+ return state;
+ }
+
+ private void restoreFindDialogState(Map state) {
+ if (state.containsKey(FIND_TEXT)) {
+ findField.setText((String) state.get(FIND_TEXT));
+ }
+ if (state.containsKey(REPLACE_TEXT)) {
+ replaceField.setText((String) state.get(REPLACE_TEXT));
+ }
+ if (state.containsKey(IGNORE_CASE)) {
+ ignoreCaseBox.setSelected((Boolean) state.get(IGNORE_CASE));
+ }
+ if (state.containsKey(SEARCH_ALL_FILES)) {
+ searchAllFilesBox.setSelected((Boolean) state.get(SEARCH_ALL_FILES));
+ }
+ if (state.containsKey(WRAP_AROUND)) {
+ wrapAroundBox.setSelected((Boolean) state.get(WRAP_AROUND));
+ }
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ javax.swing.JLabel findLabel = new javax.swing.JLabel();
+ findField = new javax.swing.JTextField();
+ javax.swing.JLabel replaceLabel = new javax.swing.JLabel();
+ replaceField = new javax.swing.JTextField();
+ ignoreCaseBox = new javax.swing.JCheckBox();
+ wrapAroundBox = new javax.swing.JCheckBox();
+ searchAllFilesBox = new javax.swing.JCheckBox();
+ buttonsContainer = new javax.swing.JPanel();
+ findButton = new javax.swing.JButton();
+ previousButton = new javax.swing.JButton();
+ replaceFindButton = new javax.swing.JButton();
+ replaceButton = new javax.swing.JButton();
+ replaceAllButton = new javax.swing.JButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setTitle(_("Find"));
+
+ findLabel.setText(_("Find:"));
+
+ findField.setColumns(20);
+
+ replaceLabel.setText(_("Replace with:"));
+
+ replaceField.setColumns(20);
+
+ ignoreCaseBox.setSelected(true);
+ ignoreCaseBox.setText(_("Ignore Case"));
+
+ wrapAroundBox.setSelected(true);
+ wrapAroundBox.setText(_("Wrap Around"));
+
+ searchAllFilesBox.setText(_("Search all Sketch Tabs"));
+
+ findButton.setText(_("Find"));
+ findButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ findButtonActionPerformed(evt);
+ }
+ });
+ buttonsContainer.add(findButton);
+
+ previousButton.setText(_("Previous"));
+ previousButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ previousButtonActionPerformed(evt);
+ }
+ });
+ buttonsContainer.add(previousButton);
+
+ replaceFindButton.setText(_("Replace & Find"));
+ replaceFindButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ replaceFindButtonActionPerformed(evt);
+ }
+ });
+ buttonsContainer.add(replaceFindButton);
+
+ replaceButton.setText(_("Replace"));
+ replaceButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ replaceButtonActionPerformed(evt);
+ }
+ });
+ buttonsContainer.add(replaceButton);
+
+ replaceAllButton.setText(_("Replace All"));
+ replaceAllButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ replaceAllButtonActionPerformed(evt);
+ }
+ });
+ buttonsContainer.add(replaceAllButton);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(replaceLabel)
+ .addComponent(findLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(findField)
+ .addComponent(replaceField)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(searchAllFilesBox)
+ .addComponent(wrapAroundBox)
+ .addComponent(ignoreCaseBox))
+ .addGap(0, 0, Short.MAX_VALUE))))
+ .addComponent(buttonsContainer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(findLabel)
+ .addComponent(findField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(replaceLabel)
+ .addComponent(replaceField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ignoreCaseBox)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(wrapAroundBox)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(searchAllFilesBox)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(buttonsContainer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void findButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_findButtonActionPerformed
+ findNext();
+ }//GEN-LAST:event_findButtonActionPerformed
+
+ private void previousButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_previousButtonActionPerformed
+ findPrevious();
+ }//GEN-LAST:event_previousButtonActionPerformed
+
+ private void replaceFindButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_replaceFindButtonActionPerformed
+ replaceAndFindNext();
+ }//GEN-LAST:event_replaceFindButtonActionPerformed
+
+ private void replaceButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_replaceButtonActionPerformed
+ replace();
+ }//GEN-LAST:event_replaceButtonActionPerformed
+
+ private void replaceAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_replaceAllButtonActionPerformed
+ replaceAll();
+ }//GEN-LAST:event_replaceAllButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JPanel buttonsContainer;
+ private javax.swing.JButton findButton;
+ private javax.swing.JTextField findField;
+ private javax.swing.JCheckBox ignoreCaseBox;
+ private javax.swing.JButton previousButton;
+ private javax.swing.JButton replaceAllButton;
+ private javax.swing.JButton replaceButton;
+ private javax.swing.JTextField replaceField;
+ private javax.swing.JButton replaceFindButton;
+ private javax.swing.JCheckBox searchAllFilesBox;
+ private javax.swing.JCheckBox wrapAroundBox;
+ // End of variables declaration//GEN-END:variables
+
+ private boolean find(boolean wrap, boolean backwards, boolean searchTabs, int originTab) {
+ boolean wrapNeeded = false;
+ String search = findField.getText();
+
+ if (search.length() == 0) {
+ return false;
+ }
+
+ String text = editor.getText();
+
+ if (ignoreCaseBox.isSelected()) {
+ search = search.toLowerCase();
+ text = text.toLowerCase();
+ }
+
+ int nextIndex;
+ if (!backwards) {
+ // int selectionStart = editor.textarea.getSelectionStart();
+ int selectionEnd = editor.getSelectionStop();
+
+ nextIndex = text.indexOf(search, selectionEnd);
+ if (wrap && nextIndex == -1) {
+ // if wrapping, a second chance is ok, start from beginning
+ wrapNeeded = true;
+ }
+ } else {
+ // int selectionStart = editor.textarea.getSelectionStart();
+ int selectionStart = editor.getSelectionStart() - 1;
+
+ if (selectionStart >= 0) {
+ nextIndex = text.lastIndexOf(search, selectionStart);
+ } else {
+ nextIndex = -1;
+ }
+ if (wrap && nextIndex == -1) {
+ // if wrapping, a second chance is ok, start from the end
+ wrapNeeded = true;
+ }
+ }
+
+ if (nextIndex == -1) {
+ // Nothing found on this tab: Search other tabs if required
+ if (searchTabs) {
+ // editor.
+ Sketch sketch = editor.getSketch();
+ if (sketch.getCodeCount() > 1) {
+ int realCurrentTab = sketch.getCodeIndex(sketch.getCurrentCode());
+
+ if (originTab != realCurrentTab) {
+ if (originTab < 0) {
+ originTab = realCurrentTab;
+ }
+
+ if (!wrap) {
+ if ((!backwards && realCurrentTab + 1 >= sketch.getCodeCount()) || (backwards && realCurrentTab - 1 < 0)) {
+ return false; // Can't continue without wrap
+ }
+ }
+
+ if (backwards) {
+ sketch.handlePrevCode();
+ this.setVisible(true);
+ int l = editor.getText().length() - 1;
+ editor.setSelection(l, l);
+ } else {
+ sketch.handleNextCode();
+ this.setVisible(true);
+ editor.setSelection(0, 0);
+ }
+
+ return find(wrap, backwards, true, originTab);
+ }
+ }
+ }
+
+ if (wrapNeeded) {
+ nextIndex = backwards ? text.lastIndexOf(search) : text.indexOf(search, 0);
+ }
+ }
+
+ if (nextIndex != -1) {
+ editor.setSelection(nextIndex, nextIndex + search.length());
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Replace the current selection with whatever's in the replacement text
+ * field.
+ */
+ private void replace() {
+ if (findField.getText().length() == 0) {
+ return;
+ }
+
+ int newpos = editor.getSelectionStart() - findField.getText().length();
+ if (newpos < 0) {
+ newpos = 0;
+ }
+ editor.setSelection(newpos, newpos);
+
+ boolean foundAtLeastOne = false;
+
+ if (find(false, false, searchAllFilesBox.isSelected(), -1)) {
+ foundAtLeastOne = true;
+ editor.setSelectedText(replaceField.getText());
+ editor.getSketch().setModified(true); // TODO is this necessary?
+ }
+
+ if (!foundAtLeastOne) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ }
+
+ /**
+ * Replace the current selection with whatever's in the replacement text
+ * field, and then find the next match
+ */
+ private void replaceAndFindNext() {
+ replace();
+ findNext();
+ }
+
+ /**
+ * Replace everything that matches by doing find and replace alternately until
+ * nothing more found.
+ */
+ private void replaceAll() {
+ if (findField.getText().length() == 0) {
+ return;
+ }
+
+ if (searchAllFilesBox.isSelected()) {
+ editor.getSketch().setCurrentCode(0); // select the first tab
+ }
+
+ editor.setSelection(0, 0); // move to the beginning
+
+ boolean foundAtLeastOne = false;
+ while (true) {
+ if (find(false, false, searchAllFilesBox.isSelected(), -1)) {
+ foundAtLeastOne = true;
+ editor.setSelectedText(replaceField.getText());
+ editor.getSketch().setModified(true); // TODO is this necessary?
+ } else {
+ break;
+ }
+ }
+ if (!foundAtLeastOne) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+ }
+
+ public void findNext() {
+ if (!find(wrapAroundBox.isSelected(), false, searchAllFilesBox.isSelected(), -1)) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+ }
+
+ public void findPrevious() {
+ if (!find(wrapAroundBox.isSelected(), true, searchAllFilesBox.isSelected(), -1)) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+ }
+
+ public void setFindText(String text) {
+ if (text == null) {
+ return;
+ }
+ findField.setText(text);
+ }
+}
diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java
index a6c635f5b..2b0cbadfa 100644
--- a/app/src/processing/app/Base.java
+++ b/app/src/processing/app/Base.java
@@ -92,6 +92,7 @@ public class Base {
public static volatile Base INSTANCE;
public static SplashScreenHelper splashScreenHelper = new SplashScreenHelper(SplashScreen.getSplashScreen());
+ public static Map FIND_DIALOG_STATE = new HashMap();
// set to true after the first time the menu is built.
// so that the errors while building don't show up again.
diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java
index c774afbb5..f4cea1d3d 100644
--- a/app/src/processing/app/Editor.java
+++ b/app/src/processing/app/Editor.java
@@ -25,6 +25,7 @@ package processing.app;
import cc.arduino.packages.MonitorFactory;
import cc.arduino.view.StubMenuListener;
+import cc.arduino.view.findreplace.FindReplace;
import com.google.common.base.Predicate;
import com.jcraft.jsch.JSchException;
import jssc.SerialPortException;
@@ -1446,7 +1447,7 @@ public class Editor extends JFrame implements RunnerListener {
findItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (find == null) {
- find = new FindReplace(Editor.this);
+ find = new FindReplace(Editor.this, Base.FIND_DIALOG_STATE);
}
if (!OSUtils.isMacOS()) {
find.setFindText(getSelectedText());
@@ -1482,7 +1483,7 @@ public class Editor extends JFrame implements RunnerListener {
useSelectionForFindItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (find == null) {
- find = new FindReplace(Editor.this);
+ find = new FindReplace(Editor.this, Base.FIND_DIALOG_STATE);
}
find.setFindText(getSelectedText());
}
diff --git a/app/src/processing/app/FindReplace.java b/app/src/processing/app/FindReplace.java
deleted file mode 100644
index 116d8fa5c..000000000
--- a/app/src/processing/app/FindReplace.java
+++ /dev/null
@@ -1,465 +0,0 @@
-/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2004-08 Ben Fry and Casey Reas
- Copyright (c) 2001-04 Massachusetts Institute of Technology
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-package processing.app;
-import static processing.app.I18n._;
-
-import java.awt.*;
-import java.awt.event.*;
-
-import javax.swing.*;
-import javax.swing.border.Border;
-
-import processing.app.helpers.OSUtils;
-
-
-/**
- * Find & Replace window for the Processing editor.
- *
- * One major annoyance in this is that the window is re-created each time
- * that "Find" is called. This is because Mac OS X has a strange focus
- * issue with windows that are re-shown with setVisible() or show().
- * requestFocusInWindow() properly sets the focus to the find field,
- * however, just a short moment later, the focus is set to null. Even
- * trying to catch this scenario and request it again doesn't seem to work.
- * Most likely this is some annoyance buried deep in one of Apple's docs,
- * or in the doc for the focus stuff (I tend to think the former because
- * Windows doesn't seem to be quite so beligerent). Filed as
- * Bug 244
- * should anyone have clues about how to fix.
- */
-@SuppressWarnings("serial")
-public class FindReplace extends JFrame implements ActionListener {
-
- private Editor editor;
-
- private JTextField findField;
- private JTextField replaceField;
- private static String findString;
- private static String replaceString;
-
- private JButton replaceButton;
- private JButton replaceAllButton;
- private JButton replaceFindButton;
- private JButton previousButton;
- private JButton findButton;
-
- private JCheckBox ignoreCaseBox;
- private static boolean ignoreCase = true;
-
- private JCheckBox wrapAroundBox;
- private static boolean wrapAround = true;
-
- private JCheckBox searchAllFilesBox;
- private static boolean searchAllFiles = false;
-
- public FindReplace(Editor editor) {
- super(_("Find"));
- this.editor = editor;
-
- JPanel contentPanel = new JPanel();
- Border padding = BorderFactory.createEmptyBorder(10, 10, 10, 10);
- contentPanel.setBorder(padding);
- setContentPane(contentPanel);
-
- JLabel findLabel = new JLabel(_("Find:"));
- findField = new JTextField(20);
- JLabel replaceLabel = new JLabel(_("Replace with:"));
- replaceField = new JTextField(20);
-
- // Fill the findString with selected text if no previous value
- if (editor.getSelectedText() != null
- && editor.getSelectedText().length() > 0)
- findString = editor.getSelectedText();
-
- if (findString != null)
- findField.setText(findString);
- if (replaceString != null)
- replaceField.setText(replaceString);
-
- ignoreCaseBox = new JCheckBox(_("Ignore Case"));
- ignoreCaseBox.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ignoreCase = ignoreCaseBox.isSelected();
- }
- });
- ignoreCaseBox.setSelected(ignoreCase);
-
- wrapAroundBox = new JCheckBox(_("Wrap Around"));
- wrapAroundBox.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- wrapAround = wrapAroundBox.isSelected();
- }
- });
- wrapAroundBox.setSelected(wrapAround);
-
- searchAllFilesBox = new JCheckBox(_("Search all Sketch Tabs"));
- searchAllFilesBox.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- searchAllFiles = searchAllFilesBox.isSelected();
- }
- });
- searchAllFilesBox.setSelected(searchAllFiles);
-
- JPanel checkboxPanel = new JPanel();
- checkboxPanel.setLayout(new BoxLayout(checkboxPanel, BoxLayout.PAGE_AXIS));
- checkboxPanel.add(ignoreCaseBox);
- checkboxPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- checkboxPanel.add(wrapAroundBox);
- checkboxPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- checkboxPanel.add(searchAllFilesBox);
-
- replaceAllButton = new JButton(_("Replace All"));
- replaceAllButton.addActionListener(this);
- replaceButton = new JButton(_("Replace"));
- replaceButton.addActionListener(this);
- replaceFindButton = new JButton(_("Replace & Find"));
- replaceFindButton.addActionListener(this);
- previousButton = new JButton(_("Previous"));
- previousButton.addActionListener(this);
- findButton = new JButton(_("Find"));
- findButton.addActionListener(this);
-
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
-
- // ordering of buttons is different on mac versus pc
- if (OSUtils.isMacOS()) {
- buttonPanel.add(replaceAllButton);
- buttonPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- buttonPanel.add(replaceButton);
- buttonPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- buttonPanel.add(replaceFindButton);
- buttonPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- buttonPanel.add(previousButton);
- buttonPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- buttonPanel.add(findButton);
-
- } else {
- buttonPanel.add(findButton);
- buttonPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- buttonPanel.add(previousButton); // is this the right position for
- // non-Mac?
- buttonPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- buttonPanel.add(replaceFindButton);
- buttonPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- buttonPanel.add(replaceButton);
- buttonPanel.add(Box.createRigidArea(new Dimension(8, 0)));
- buttonPanel.add(replaceAllButton);
- }
-
- // to fix ugliness.. normally macosx java 1.3 puts an
- // ugly white border around this object, so turn it off.
- if (OSUtils.isMacOS()) {
- buttonPanel.setBorder(null);
- }
-
- // Put all components onto the dialog window
- GridBagLayout searchLayout = new GridBagLayout();
- GridBagConstraints gbc = new GridBagConstraints();
- Container pane = getContentPane();
- pane.setLayout(searchLayout);
-
- gbc.insets = new Insets(4, 4, 4, 4);
- gbc.gridx = 0;
- gbc.weightx = 0.0;
- gbc.weighty = 0.0;
- gbc.fill = GridBagConstraints.NONE;
- gbc.anchor = GridBagConstraints.LINE_END;
- pane.add(findLabel, gbc);
- gbc.gridx = 1;
- gbc.weightx = 1.0;
- gbc.fill = GridBagConstraints.HORIZONTAL;
- gbc.anchor = GridBagConstraints.LINE_START;
- pane.add(findField, gbc);
- gbc.gridx = 0;
- gbc.gridy = 1;
- gbc.weightx = 0.0;
- gbc.fill = GridBagConstraints.NONE;
- gbc.anchor = GridBagConstraints.LINE_END;
- pane.add(replaceLabel, gbc);
- gbc.gridx = 1;
- gbc.weightx = 1.0;
- gbc.fill = GridBagConstraints.HORIZONTAL;
- gbc.anchor = GridBagConstraints.LINE_START;
- pane.add(replaceField, gbc);
- gbc.gridx = 1;
- gbc.gridy = 2;
- gbc.weighty = 0.0;
- gbc.fill = GridBagConstraints.NONE;
- pane.add(checkboxPanel, gbc);
- gbc.anchor = GridBagConstraints.CENTER;
- gbc.gridwidth = 2;
- gbc.gridx = 0;
- gbc.gridy = 3;
- gbc.insets = new Insets(12, 4, 4, 4);
- pane.add(buttonPanel, gbc);
-
- pack();
- setResizable(false);
- // centers the dialog on thew screen
- setLocationRelativeTo(null);
-
- // make the find button the blinky default
- getRootPane().setDefaultButton(findButton);
-
- setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
- addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- handleClose();
- }
- });
- Base.registerWindowCloseKeys(getRootPane(), new ActionListener() {
- public void actionPerformed(ActionEvent actionEvent) {
- // hide();
- handleClose();
- }
- });
- Base.setIcon(this);
-
- // hack to to get first field to focus properly on osx
- addWindowListener(new WindowAdapter() {
- public void windowActivated(WindowEvent e) {
- // System.out.println("activating");
- /* boolean ok = */findField.requestFocusInWindow();
- // System.out.println("got " + ok);
- findField.selectAll();
- }
- });
- }
-
- public void handleClose() {
- // System.out.println("handling close now");
- findString = findField.getText();
- replaceString = replaceField.getText();
-
- // this object should eventually become dereferenced
- setVisible(false);
- }
-
- /*
- public void show() {
- findField.requestFocusInWindow();
- super.show();
- //findField.selectAll();
- //findField.requestFocus();
- }
- */
-
-
- public void actionPerformed(ActionEvent e) {
- Object source = e.getSource();
-
- if (source == findButton) {
- findNext();
-
- } else if (source == previousButton) {
- findPrevious();
-
- } else if (source == replaceFindButton) {
- replaceAndFindNext();
-
- } else if (source == replaceButton) {
- replace();
-
- } else if (source == replaceAllButton) {
- replaceAll();
- }
- }
-
- // look for the next instance of the find string to be found
- // once found, select it (and go to that line)
-
- private boolean find(boolean wrap, boolean backwards, boolean searchTabs,
- int originTab) {
- // System.out.println("Find: " + originTab);
- boolean wrapNeeded = false;
- String search = findField.getText();
- // System.out.println("finding for " + search + " " + findString);
- // this will catch "find next" being called when no search yet
- if (search.length() == 0)
- return false;
-
- String text = editor.getText();
-
- if (ignoreCase) {
- search = search.toLowerCase();
- text = text.toLowerCase();
- }
-
- int nextIndex;
- if (!backwards) {
- // int selectionStart = editor.textarea.getSelectionStart();
- int selectionEnd = editor.getSelectionStop();
-
- nextIndex = text.indexOf(search, selectionEnd);
- if (wrap && nextIndex == -1) {
- // if wrapping, a second chance is ok, start from beginning
- wrapNeeded = true;
- }
- } else {
- // int selectionStart = editor.textarea.getSelectionStart();
- int selectionStart = editor.getSelectionStart() - 1;
-
- if (selectionStart >= 0) {
- nextIndex = text.lastIndexOf(search, selectionStart);
- } else {
- nextIndex = -1;
- }
- if (wrap && nextIndex == -1) {
- // if wrapping, a second chance is ok, start from the end
- wrapNeeded = true;
- }
- }
-
- if (nextIndex == -1) {
- // Nothing found on this tab: Search other tabs if required
- if (searchTabs) {
- // editor.
- Sketch sketch = editor.getSketch();
- if (sketch.getCodeCount() > 1) {
- int realCurrentTab = sketch.getCodeIndex(sketch.getCurrentCode());
-
- if (originTab != realCurrentTab) {
- if (originTab < 0)
- originTab = realCurrentTab;
-
- if (!wrap)
- if ((!backwards && realCurrentTab + 1 >= sketch.getCodeCount())
- || (backwards && realCurrentTab - 1 < 0))
- return false; // Can't continue without wrap
-
- if (backwards) {
- sketch.handlePrevCode();
- this.setVisible(true);
- int l = editor.getText().length() - 1;
- editor.setSelection(l, l);
- } else {
- sketch.handleNextCode();
- this.setVisible(true);
- editor.setSelection(0, 0);
- }
-
- return find(wrap, backwards, searchTabs, originTab);
- }
- }
- }
-
- if (wrapNeeded)
- nextIndex = backwards ? text.lastIndexOf(search) : text.indexOf(search,
- 0);
- }
-
- if (nextIndex != -1) {
- editor.setSelection(nextIndex, nextIndex + search.length());
- return true;
- }
-
- return false;
- }
-
- /**
- * Replace the current selection with whatever's in the replacement text
- * field.
- */
- public void replace() {
- if (findField.getText().length() == 0)
- return;
-
- int newpos = editor.getSelectionStart() - findField.getText().length();
- if (newpos < 0)
- newpos = 0;
- editor.setSelection(newpos, newpos);
-
- boolean foundAtLeastOne = false;
-
- if (find(false, false, searchAllFiles, -1)) {
- foundAtLeastOne = true;
- editor.setSelectedText(replaceField.getText());
- editor.getSketch().setModified(true); // TODO is this necessary?
- }
-
- if (!foundAtLeastOne) {
- Toolkit.getDefaultToolkit().beep();
- }
-
- }
-
- /**
- * Replace the current selection with whatever's in the replacement text
- * field, and then find the next match
- */
- public void replaceAndFindNext() {
- replace();
- findNext();
- }
-
- /**
- * Replace everything that matches by doing find and replace alternately until
- * nothing more found.
- */
- public void replaceAll() {
- if (findField.getText().length() == 0)
- return;
-
- if (searchAllFiles)
- editor.getSketch().setCurrentCode(0); // select the first tab
-
- editor.setSelection(0, 0); // move to the beginning
-
- boolean foundAtLeastOne = false;
- while (true) {
- if (find(false, false, searchAllFiles, -1)) {
- foundAtLeastOne = true;
- editor.setSelectedText(replaceField.getText());
- editor.getSketch().setModified(true); // TODO is this necessary?
- } else {
- break;
- }
- }
- if (!foundAtLeastOne) {
- Toolkit.getDefaultToolkit().beep();
- }
- }
-
- public void setFindText(String text) {
- if (text == null) {
- return;
- }
- findField.setText(text);
- findString = text;
- }
-
- public void findNext() {
- if (!find(wrapAround, false, searchAllFiles, -1)) {
- Toolkit.getDefaultToolkit().beep();
- }
- }
-
- public void findPrevious() {
- if (!find(wrapAround, true, searchAllFiles, -1)) {
- Toolkit.getDefaultToolkit().beep();
- }
- }
-
-}