1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-02-20 14:54:31 +01:00

FindReplace dialog re-done from scratch using Netbeans. This ensure proper display on every OS. Fixes #2211

This commit is contained in:
Federico Fissore 2015-06-08 12:45:33 +02:00
parent 9ab0ea6e49
commit 8465202264
5 changed files with 660 additions and 467 deletions

View File

@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Find&quot;)" type="code"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="replaceLabel" min="-2" max="-2" attributes="0"/>
<Component id="findLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="findField" max="32767" attributes="0"/>
<Component id="replaceField" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="searchAllFilesBox" min="-2" max="-2" attributes="0"/>
<Component id="wrapAroundBox" min="-2" max="-2" attributes="0"/>
<Component id="ignoreCaseBox" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
<Component id="buttonsContainer" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="findLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="findField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="replaceLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="replaceField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="ignoreCaseBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="wrapAroundBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="searchAllFilesBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="buttonsContainer" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="findLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Find:&quot;)" type="code"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JTextField" name="findField">
<Properties>
<Property name="columns" type="int" value="20"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="replaceLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Replace with:&quot;)" type="code"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JTextField" name="replaceField">
<Properties>
<Property name="columns" type="int" value="20"/>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="ignoreCaseBox">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Ignore Case&quot;)" type="code"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="wrapAroundBox">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Wrap Around&quot;)" type="code"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="searchAllFilesBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Search all Sketch Tabs&quot;)" type="code"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="buttonsContainer">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
<SubComponents>
<Component class="javax.swing.JButton" name="findButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Find&quot;)" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="previousButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Previous&quot;)" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="previousButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="replaceFindButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Replace &amp; Find&quot;)" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="replaceFindButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="replaceButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Replace&quot;)" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="replaceButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="replaceAllButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="_(&quot;Replace All&quot;)" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="replaceAllButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -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<String, Object> 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<String, Object> findDialogState() {
Map<String, Object> state = new HashMap<String, Object>();
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<String, Object> 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")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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();
}// </editor-fold>//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);
}
}

View File

@ -92,6 +92,7 @@ public class Base {
public static volatile Base INSTANCE;
public static SplashScreenHelper splashScreenHelper = new SplashScreenHelper(SplashScreen.getSplashScreen());
public static Map<String, Object> FIND_DIALOG_STATE = new HashMap<String, Object>();
// set to true after the first time the menu is built.
// so that the errors while building don't show up again.

View File

@ -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());
}

View File

@ -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.
* <p/>
* 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
* <A HREF="http://dev.processing.org/bugs/show_bug.cgi?id=244"> Bug 244</A>
* 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();
}
}
}