1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-01-17 06:52:18 +01:00

Find / Replace dialog cleanup and improvements (Peter Lewis)

Adds Find Previous and Use Selection for Find; various other cleanups.
Changes Mac keyboard shortcut for Redo from Command-Y to
Command-Shift-Z.

http://code.google.com/p/arduino/issues/detail?id=825
This commit is contained in:
David A. Mellis 2012-03-02 17:56:17 -05:00
parent 599a9052c9
commit 0db8bdbbb0
2 changed files with 195 additions and 124 deletions

View File

@ -1120,7 +1120,11 @@ public class Editor extends JFrame implements RunnerListener {
undoItem.addActionListener(undoAction = new UndoAction()); undoItem.addActionListener(undoAction = new UndoAction());
menu.add(undoItem); menu.add(undoItem);
if (!Base.isMacOS()) {
redoItem = newJMenuItem(_("Redo"), 'Y'); redoItem = newJMenuItem(_("Redo"), 'Y');
} else {
redoItem = newJMenuItemShift(_("Redo"), 'Z');
}
redoItem.addActionListener(redoAction = new RedoAction()); redoItem.addActionListener(redoAction = new RedoAction());
menu.add(redoItem); menu.add(redoItem);
@ -1232,14 +1236,33 @@ public class Editor extends JFrame implements RunnerListener {
item.addActionListener(new ActionListener() { item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (find != null) { if (find != null) {
//find.find(true); find.findNext();
//FindReplace find = new FindReplace(Editor.this); //.show();
find.find(true);
} }
} }
}); });
menu.add(item); menu.add(item);
item = newJMenuItemShift(_("Find Previous"), 'G');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (find != null) {
find.findPrevious();
}
}
});
menu.add(item);
item = newJMenuItem(_("Use Selection For Find"), 'E');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (find == null) {
find = new FindReplace(Editor.this);
}
find.setFindText( getSelectedText() );
}
});
menu.add(item);
return menu; return menu;
} }

View File

@ -46,8 +46,9 @@ import javax.swing.*;
*/ */
public class FindReplace extends JFrame implements ActionListener { public class FindReplace extends JFrame implements ActionListener {
static final int BIG = 13; static final int EDGE = Base.isMacOS() ? 20 : 13;
static final int SMALL = 6; static final int SMALL = 6;
static final int BUTTONGAP = 12; // 12 is correct for Mac, other numbers may be required for other platofrms
Editor editor; Editor editor;
@ -59,14 +60,14 @@ public class FindReplace extends JFrame implements ActionListener {
JButton replaceButton; JButton replaceButton;
JButton replaceAllButton; JButton replaceAllButton;
JButton replaceFindButton; JButton replaceFindButton;
JButton previousButton;
JButton findButton; JButton findButton;
JCheckBox ignoreCaseBox; JCheckBox ignoreCaseBox;
static boolean ignoreCase = true; static boolean ignoreCase = true;
/// true when there's something selected in the editor JCheckBox wrapAroundBox;
boolean found; static boolean wrapAround = true;
public FindReplace(Editor editor) { public FindReplace(Editor editor) {
super("Find"); super("Find");
@ -77,23 +78,66 @@ public class FindReplace extends JFrame implements ActionListener {
pain.setLayout(null); pain.setLayout(null);
JLabel findLabel = new JLabel(_("Find:")); JLabel findLabel = new JLabel(_("Find:"));
Dimension d0 = findLabel.getPreferredSize();
JLabel replaceLabel = new JLabel(_("Replace with:")); JLabel replaceLabel = new JLabel(_("Replace with:"));
Dimension d1 = replaceLabel.getPreferredSize(); Dimension labelDimension = replaceLabel.getPreferredSize();
pain.add(findLabel); pain.add(findLabel);
pain.add(replaceLabel); pain.add(replaceLabel);
pain.add(findField = new JTextField(20)); pain.add(findField = new JTextField(20));
pain.add(replaceField = new JTextField(20)); pain.add(replaceField = new JTextField(20));
Dimension d2 = findField.getPreferredSize(); int fieldHeight = findField.getPreferredSize().height;
if (findString != null) findField.setText(findString); if (findString != null) findField.setText(findString);
if (replaceString != null) replaceField.setText(replaceString); if (replaceString != null) replaceField.setText(replaceString);
//System.out.println("setting find str to " + findString); //System.out.println("setting find str to " + findString);
//findField.requestFocusInWindow(); //findField.requestFocusInWindow();
//pain.setDefault ignoreCaseBox = new JCheckBox(_("Ignore Case"));
ignoreCaseBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ignoreCase = ignoreCaseBox.isSelected();
}
});
ignoreCaseBox.setSelected(ignoreCase);
pain.add(ignoreCaseBox);
wrapAroundBox = new JCheckBox(_("Wrap Around"));
wrapAroundBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
wrapAround = wrapAroundBox.isSelected();
}
});
wrapAroundBox.setSelected(wrapAround);
pain.add(wrapAroundBox);
JPanel buttons = new JPanel();
buttons.setLayout(new FlowLayout(FlowLayout.CENTER,BUTTONGAP,0));
// ordering is different on mac versus pc
if (Base.isMacOS()) {
buttons.add(replaceAllButton = new JButton(_("Replace All")));
buttons.add(replaceButton = new JButton(_("Replace")));
buttons.add(replaceFindButton = new JButton(_("Replace & Find")));
buttons.add(previousButton = new JButton(_("Previous")));
buttons.add(findButton = new JButton(_("Find")));
} else {
buttons.add(findButton = new JButton(_("Find")));
buttons.add(previousButton = new JButton(_("Previous"))); // is this the right position for non-Mac?
buttons.add(replaceFindButton = new JButton(_("Replace & Find")));
buttons.add(replaceButton = new JButton(_("Replace")));
buttons.add(replaceAllButton = new JButton(_("Replace All")));
}
pain.add(buttons);
// to fix ugliness.. normally macosx java 1.3 puts an
// ugly white border around this object, so turn it off.
if (Base.isMacOS()) {
buttons.setBorder(null);
}
/* /*
findField.addFocusListener(new FocusListener() { findField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) { public void focusGained(FocusEvent e) {
@ -109,92 +153,74 @@ public class FindReplace extends JFrame implements ActionListener {
}); });
*/ */
Dimension buttonsDimension = buttons.getPreferredSize();
int visibleButtonWidth = buttonsDimension.width - 2 * BUTTONGAP;
int fieldWidth = visibleButtonWidth - (labelDimension.width + SMALL);
// +1 since it's better to tend downwards // +1 since it's better to tend downwards
int yoff = (1 + d2.height - d1.height) / 2; int yoff = (1 + fieldHeight - labelDimension.height) / 2;
findLabel.setBounds(BIG + (d1.width-d0.width) + yoff, BIG, int ypos = EDGE;
d1.width, d1.height);
replaceLabel.setBounds(BIG, BIG + d2.height + SMALL + yoff,
d1.width, d1.height);
//ignoreCase = true; int labelWidth = findLabel.getPreferredSize().width;
ignoreCaseBox = new JCheckBox(_("Ignore Case")); findLabel.setBounds(EDGE + (labelDimension.width-labelWidth), ypos + yoff, // + yoff was added to the wrong field
ignoreCaseBox.addActionListener(new ActionListener() { labelWidth, labelDimension.height);
public void actionPerformed(ActionEvent e) { findField.setBounds(EDGE + labelDimension.width + SMALL, ypos,
ignoreCase = ignoreCaseBox.isSelected(); fieldWidth, fieldHeight);
}
});
ignoreCaseBox.setSelected(ignoreCase);
pain.add(ignoreCaseBox);
// ypos += fieldHeight + SMALL;
JPanel buttons = new JPanel(); labelWidth = replaceLabel.getPreferredSize().width;
buttons.setLayout(new FlowLayout()); replaceLabel.setBounds(EDGE + (labelDimension.width-labelWidth), ypos + yoff,
labelWidth, labelDimension.height);
replaceField.setBounds(EDGE + labelDimension.width + SMALL, ypos,
fieldWidth, fieldHeight);
// ordering is different on mac versus pc ypos += fieldHeight + SMALL;
if (Base.isMacOS()) {
buttons.add(replaceAllButton = new JButton(_("Replace All")));
buttons.add(replaceButton = new JButton(_("Replace")));
buttons.add(replaceFindButton = new JButton(_("Replace & Find")));
buttons.add(findButton = new JButton(_("Find")));
} else { ignoreCaseBox.setBounds(EDGE + labelDimension.width + SMALL,
buttons.add(findButton = new JButton(_("Find"))); ypos,
buttons.add(replaceFindButton = new JButton(_("Replace & Find"))); (fieldWidth-SMALL)/2, fieldHeight);
buttons.add(replaceButton = new JButton(_("Replace")));
buttons.add(replaceAllButton = new JButton(_("Replace All")));
}
pain.add(buttons);
// to fix ugliness.. normally macosx java 1.3 puts an wrapAroundBox.setBounds(EDGE + labelDimension.width + SMALL + (fieldWidth-SMALL)/2 + SMALL,
// ugly white border around this object, so turn it off. ypos,
if (Base.isMacOS()) { (fieldWidth-SMALL)/2, fieldHeight);
buttons.setBorder(null);
}
Dimension d3 = buttons.getPreferredSize(); ypos += fieldHeight + SMALL;
//buttons.setBounds(BIG, BIG + d2.height*2 + SMALL + BIG,
buttons.setBounds(BIG, BIG + d2.height*3 + SMALL*2 + BIG,
d3.width, d3.height);
// buttons.setBounds(EDGE-BUTTONGAP, ypos,
buttonsDimension.width, buttonsDimension.height);
findField.setBounds(BIG + d1.width + SMALL, BIG, ypos += buttonsDimension.height + EDGE;
d3.width - (d1.width + SMALL), d2.height);
replaceField.setBounds(BIG + d1.width + SMALL, BIG + d2.height + SMALL,
d3.width - (d1.width + SMALL), d2.height);
ignoreCaseBox.setBounds(BIG + d1.width + SMALL, // Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
BIG + d2.height*2 + SMALL*2,
d3.width, d2.height);
// int wide = visibleButtonWidth + EDGE*2;
int high = ypos; // butt.y + butt.height + EDGE*2 + SMALL;
pack();
Insets insets = getInsets();
System.out.println("Insets = " + insets);
setSize(wide + insets.left + insets.right,high + insets.top + insets.bottom);
setLocationRelativeTo( null ); // center
// setBounds((screen.width - wide) / 2, (screen.height - high) / 2, wide, high);
replaceButton.addActionListener(this); replaceButton.addActionListener(this);
replaceAllButton.addActionListener(this); replaceAllButton.addActionListener(this);
replaceFindButton.addActionListener(this); replaceFindButton.addActionListener(this);
findButton.addActionListener(this); findButton.addActionListener(this);
previousButton.addActionListener(this);
// you mustn't replace what you haven't found, my son // you mustn't replace what you haven't found, my son
replaceButton.setEnabled(false); // semantics of replace are "replace the current selection with the replace field"
replaceFindButton.setEnabled(false); // so whether we have found before or not is irrelevent
// replaceButton.setEnabled(false);
// so that typing will go straight to this field // replaceFindButton.setEnabled(false);
//findField.requestFocus();
// make the find button the blinky default // make the find button the blinky default
getRootPane().setDefaultButton(findButton); getRootPane().setDefaultButton(findButton);
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int wide = d3.width + BIG*2;
Rectangle butt = buttons.getBounds(); // how big is your butt?
int high = butt.y + butt.height + BIG*2 + SMALL;
setBounds((screen.width - wide) / 2,
(screen.height - high) / 2, wide, high);
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { public void windowClosing(WindowEvent e) {
@ -245,11 +271,13 @@ public class FindReplace extends JFrame implements ActionListener {
Object source = e.getSource(); Object source = e.getSource();
if (source == findButton) { if (source == findButton) {
find(true); findNext();
} else if (source == previousButton) {
findPrevious();
} else if (source == replaceFindButton) { } else if (source == replaceFindButton) {
replace(); replaceAndFindNext();
find(true);
} else if (source == replaceButton) { } else if (source == replaceButton) {
replace(); replace();
@ -260,20 +288,15 @@ public class FindReplace extends JFrame implements ActionListener {
} }
// look for the next instance of the find string // look for the next instance of the find string to be found
// to be found later than the current caret selection
// once found, select it (and go to that line) // once found, select it (and go to that line)
public void find(boolean wrap) { private boolean find(boolean wrap,boolean backwards ) {
// in case search len is zero,
// otherwise replace all will go into an infinite loop
found = false;
String search = findField.getText(); String search = findField.getText();
//System.out.println("finding for " + search + " " + findString); //System.out.println("finding for " + search + " " + findString);
// this will catch "find next" being called when no search yet // this will catch "find next" being called when no search yet
if (search.length() == 0) return; if (search.length() == 0) return false;
String text = editor.getText(); String text = editor.getText();
@ -282,28 +305,37 @@ public class FindReplace extends JFrame implements ActionListener {
text = text.toLowerCase(); text = text.toLowerCase();
} }
int nextIndex;
if (!backwards) {
//int selectionStart = editor.textarea.getSelectionStart(); //int selectionStart = editor.textarea.getSelectionStart();
int selectionEnd = editor.getSelectionStop(); int selectionEnd = editor.getSelectionStop();
int nextIndex = text.indexOf(search, selectionEnd); nextIndex = text.indexOf(search, selectionEnd);
if (nextIndex == -1) { if (wrap && nextIndex == -1) {
if (wrap) {
// if wrapping, a second chance is ok, start from beginning // if wrapping, a second chance is ok, start from beginning
nextIndex = text.indexOf(search, 0); nextIndex = text.indexOf(search, 0);
} }
} else {
//int selectionStart = editor.textarea.getSelectionStart();
int selectionStart = editor.getSelectionStart()-1;
if (nextIndex == -1) { if ( selectionStart >= 0 ) {
found = false; nextIndex = text.lastIndexOf(search, selectionStart);
replaceButton.setEnabled(false); } else {
replaceFindButton.setEnabled(false); nextIndex = -1;
//Toolkit.getDefaultToolkit().beep(); }
return; if (wrap && nextIndex == -1) {
// if wrapping, a second chance is ok, start from the end
nextIndex = text.lastIndexOf(search);
} }
} }
found = true;
replaceButton.setEnabled(true); if (nextIndex != -1) {
replaceFindButton.setEnabled(true);
editor.setSelection(nextIndex, nextIndex + search.length()); editor.setSelection(nextIndex, nextIndex + search.length());
} else {
//Toolkit.getDefaultToolkit().beep();
}
return nextIndex != -1;
} }
@ -312,28 +344,18 @@ public class FindReplace extends JFrame implements ActionListener {
* replacement text field. * replacement text field.
*/ */
public void replace() { public void replace() {
if (!found) return; // don't replace if nothing found
// check to see if the document has wrapped around
// otherwise this will cause an infinite loop
String sel = editor.getSelectedText();
if (sel.equals(replaceField.getText())) {
found = false;
replaceButton.setEnabled(false);
replaceFindButton.setEnabled(false);
return;
}
editor.setSelectedText(replaceField.getText()); editor.setSelectedText(replaceField.getText());
//editor.setSketchModified(true);
//editor.sketch.setCurrentModified(true);
editor.getSketch().setModified(true); // TODO is this necessary? editor.getSketch().setModified(true); // TODO is this necessary?
// don't allow a double replace
replaceButton.setEnabled(false);
replaceFindButton.setEnabled(false);
} }
/**
* 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 * Replace everything that matches by doing find and replace
@ -343,9 +365,35 @@ public class FindReplace extends JFrame implements ActionListener {
// move to the beginning // move to the beginning
editor.setSelection(0, 0); editor.setSelection(0, 0);
do { boolean foundAtLeastOne = false;
find(false); while ( true ) {
if ( find(false,false) ) {
foundAtLeastOne = true;
replace(); replace();
} while (found); } else {
break;
} }
}
if ( !foundAtLeastOne ) {
Toolkit.getDefaultToolkit().beep();
}
}
public void setFindText( String t ) {
findField.setText( t );
findString = t;
}
public void findNext() {
if ( !find( wrapAround, false ) ) {
Toolkit.getDefaultToolkit().beep();
}
}
public void findPrevious() {
if ( !find( wrapAround, true ) ) {
Toolkit.getDefaultToolkit().beep();
}
}
} }