~ubuntu-branches/ubuntu/precise/arduino/precise

« back to all changes in this revision

Viewing changes to src/processing/app/FindReplace.java

  • Committer: Bazaar Package Importer
  • Author(s): Scott Howard
  • Date: 2010-04-13 22:32:24 UTC
  • Revision ID: james.westby@ubuntu.com-20100413223224-jduxnd0xxnkkda02
Tags: upstream-0018+dfsg
ImportĀ upstreamĀ versionĀ 0018+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
 
2
 
 
3
/*
 
4
  Part of the Processing project - http://processing.org
 
5
 
 
6
  Copyright (c) 2004-08 Ben Fry and Casey Reas
 
7
  Copyright (c) 2001-04 Massachusetts Institute of Technology
 
8
 
 
9
  This program is free software; you can redistribute it and/or modify
 
10
  it under the terms of the GNU General Public License as published by
 
11
  the Free Software Foundation; either version 2 of the License, or
 
12
  (at your option) any later version.
 
13
 
 
14
  This program is distributed in the hope that it will be useful,
 
15
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
  GNU General Public License for more details.
 
18
 
 
19
  You should have received a copy of the GNU General Public License
 
20
  along with this program; if not, write to the Free Software Foundation,
 
21
  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
22
*/
 
23
 
 
24
package processing.app;
 
25
 
 
26
import java.awt.*;
 
27
import java.awt.event.*;
 
28
import javax.swing.*;
 
29
 
 
30
 
 
31
/**
 
32
 * Find & Replace window for the Processing editor.
 
33
 * <p/>
 
34
 * One major annoyance in this is that the window is re-created each time
 
35
 * that "Find" is called. This is because Mac OS X has a strange focus
 
36
 * issue with windows that are re-shown with setVisible() or show().
 
37
 * requestFocusInWindow() properly sets the focus to the find field,
 
38
 * however, just a short moment later, the focus is set to null. Even
 
39
 * trying to catch this scenario and request it again doesn't seem to work.
 
40
 * Most likely this is some annoyance buried deep in one of Apple's docs,
 
41
 * or in the doc for the focus stuff (I tend to think the former because
 
42
 * Windows doesn't seem to be quite so beligerent). Filed as
 
43
 * <A HREF="http://dev.processing.org/bugs/show_bug.cgi?id=244"> Bug 244</A>
 
44
 * should anyone have clues about how to fix.
 
45
 */
 
46
public class FindReplace extends JFrame implements ActionListener {
 
47
 
 
48
  static final int BIG = 13;
 
49
  static final int SMALL = 6;
 
50
 
 
51
  Editor editor;
 
52
 
 
53
  JTextField findField;
 
54
  JTextField replaceField;
 
55
  static String findString;
 
56
  static String replaceString;
 
57
 
 
58
  JButton replaceButton;
 
59
  JButton replaceAllButton;
 
60
  JButton replaceFindButton;
 
61
  JButton findButton;
 
62
 
 
63
  JCheckBox ignoreCaseBox;
 
64
  static boolean ignoreCase = true;
 
65
 
 
66
  /// true when there's something selected in the editor
 
67
  boolean found;
 
68
 
 
69
 
 
70
  public FindReplace(Editor editor) {
 
71
    super("Find");
 
72
    setResizable(false);
 
73
    this.editor = editor;
 
74
 
 
75
    Container pain = getContentPane();
 
76
    pain.setLayout(null);
 
77
 
 
78
    JLabel findLabel = new JLabel("Find:");
 
79
    Dimension d0 = findLabel.getPreferredSize();
 
80
    JLabel replaceLabel = new JLabel("Replace with:");
 
81
    Dimension d1 = replaceLabel.getPreferredSize();
 
82
 
 
83
    pain.add(findLabel);
 
84
    pain.add(replaceLabel);
 
85
 
 
86
    pain.add(findField = new JTextField(20));
 
87
    pain.add(replaceField = new JTextField(20));
 
88
    Dimension d2 = findField.getPreferredSize();
 
89
 
 
90
    if (findString != null) findField.setText(findString);
 
91
    if (replaceString != null) replaceField.setText(replaceString);
 
92
    //System.out.println("setting find str to " + findString);
 
93
    //findField.requestFocusInWindow();
 
94
 
 
95
    //pain.setDefault
 
96
    /*
 
97
    findField.addFocusListener(new FocusListener() {
 
98
        public void focusGained(FocusEvent e) {
 
99
          System.out.println("Focus gained " + e.getOppositeComponent());
 
100
        }
 
101
 
 
102
        public void focusLost(FocusEvent e) {
 
103
          System.out.println("Focus lost "); // + e.getOppositeComponent());
 
104
          if (e.getOppositeComponent() == null) {
 
105
            requestFocusInWindow();
 
106
          }
 
107
        }
 
108
      });
 
109
    */
 
110
 
 
111
    // +1 since it's better to tend downwards
 
112
    int yoff = (1 + d2.height - d1.height) / 2;
 
113
 
 
114
    findLabel.setBounds(BIG + (d1.width-d0.width) + yoff, BIG,
 
115
                        d1.width, d1.height);
 
116
    replaceLabel.setBounds(BIG, BIG + d2.height + SMALL + yoff,
 
117
                           d1.width, d1.height);
 
118
 
 
119
    //ignoreCase = true;
 
120
    ignoreCaseBox = new JCheckBox("Ignore Case");
 
121
    ignoreCaseBox.addActionListener(new ActionListener() {
 
122
        public void actionPerformed(ActionEvent e) {
 
123
          ignoreCase = ignoreCaseBox.isSelected();
 
124
        }
 
125
      });
 
126
    ignoreCaseBox.setSelected(ignoreCase);
 
127
    pain.add(ignoreCaseBox);
 
128
 
 
129
    //
 
130
 
 
131
    JPanel buttons = new JPanel();
 
132
    buttons.setLayout(new FlowLayout());
 
133
 
 
134
    // ordering is different on mac versus pc
 
135
    if (Base.isMacOS()) {
 
136
      buttons.add(replaceAllButton = new JButton("Replace All"));
 
137
      buttons.add(replaceButton = new JButton("Replace"));
 
138
      buttons.add(replaceFindButton = new JButton("Replace & Find"));
 
139
      buttons.add(findButton = new JButton("Find"));
 
140
 
 
141
    } else {
 
142
      buttons.add(findButton = new JButton("Find"));
 
143
      buttons.add(replaceFindButton = new JButton("Replace & Find"));
 
144
      buttons.add(replaceButton = new JButton("Replace"));
 
145
      buttons.add(replaceAllButton = new JButton("Replace All"));
 
146
    }
 
147
    pain.add(buttons);
 
148
 
 
149
    // to fix ugliness.. normally macosx java 1.3 puts an
 
150
    // ugly white border around this object, so turn it off.
 
151
    if (Base.isMacOS()) {
 
152
      buttons.setBorder(null);
 
153
    }
 
154
 
 
155
    Dimension d3 = buttons.getPreferredSize();
 
156
    //buttons.setBounds(BIG, BIG + d2.height*2 + SMALL + BIG,
 
157
    buttons.setBounds(BIG, BIG + d2.height*3 + SMALL*2 + BIG,
 
158
                      d3.width, d3.height);
 
159
 
 
160
    //
 
161
 
 
162
    findField.setBounds(BIG + d1.width + SMALL, BIG,
 
163
                        d3.width - (d1.width + SMALL), d2.height);
 
164
    replaceField.setBounds(BIG + d1.width + SMALL, BIG + d2.height + SMALL,
 
165
                           d3.width - (d1.width + SMALL), d2.height);
 
166
 
 
167
    ignoreCaseBox.setBounds(BIG + d1.width + SMALL,
 
168
                            BIG + d2.height*2 + SMALL*2,
 
169
                            d3.width, d2.height);
 
170
 
 
171
    //
 
172
 
 
173
    replaceButton.addActionListener(this);
 
174
    replaceAllButton.addActionListener(this);
 
175
    replaceFindButton.addActionListener(this);
 
176
    findButton.addActionListener(this);
 
177
 
 
178
    // you mustn't replace what you haven't found, my son
 
179
    replaceButton.setEnabled(false);
 
180
    replaceFindButton.setEnabled(false);
 
181
 
 
182
    // so that typing will go straight to this field
 
183
    //findField.requestFocus();
 
184
 
 
185
    // make the find button the blinky default
 
186
    getRootPane().setDefaultButton(findButton);
 
187
 
 
188
    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
 
189
 
 
190
    int wide = d3.width + BIG*2;
 
191
    Rectangle butt = buttons.getBounds();  // how big is your butt?
 
192
    int high = butt.y + butt.height + BIG*2 + SMALL;
 
193
 
 
194
    setBounds((screen.width - wide) / 2,
 
195
              (screen.height - high) / 2, wide, high);
 
196
 
 
197
    setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
 
198
    addWindowListener(new WindowAdapter() {
 
199
        public void windowClosing(WindowEvent e) {
 
200
          handleClose();
 
201
        }
 
202
      });
 
203
    Base.registerWindowCloseKeys(getRootPane(), new ActionListener() {
 
204
        public void actionPerformed(ActionEvent actionEvent) {
 
205
          //hide();
 
206
          handleClose();
 
207
        }
 
208
      });
 
209
    Base.setIcon(this);
 
210
 
 
211
    // hack to to get first field to focus properly on osx
 
212
    addWindowListener(new WindowAdapter() {
 
213
        public void windowActivated(WindowEvent e) {
 
214
          //System.out.println("activating");
 
215
          /*boolean ok =*/ findField.requestFocusInWindow();
 
216
          //System.out.println("got " + ok);
 
217
          findField.selectAll();
 
218
        }
 
219
      });
 
220
  }
 
221
 
 
222
 
 
223
  public void handleClose() {
 
224
    //System.out.println("handling close now");
 
225
    findString = findField.getText();
 
226
    replaceString = replaceField.getText();
 
227
 
 
228
    // this object should eventually become dereferenced
 
229
    setVisible(false);
 
230
  }
 
231
 
 
232
 
 
233
  /*
 
234
  public void show() {
 
235
    findField.requestFocusInWindow();
 
236
    super.show();
 
237
    //findField.selectAll();
 
238
    //findField.requestFocus();
 
239
  }
 
240
  */
 
241
 
 
242
 
 
243
  public void actionPerformed(ActionEvent e) {
 
244
    Object source = e.getSource();
 
245
 
 
246
    if (source == findButton) {
 
247
      find(true);
 
248
 
 
249
    } else if (source == replaceFindButton) {
 
250
      replace();
 
251
      find(true);
 
252
 
 
253
    } else if (source == replaceButton) {
 
254
      replace();
 
255
 
 
256
    } else if (source == replaceAllButton) {
 
257
      replaceAll();
 
258
    }
 
259
  }
 
260
 
 
261
 
 
262
  // look for the next instance of the find string
 
263
  // to be found later than the current caret selection
 
264
 
 
265
  // once found, select it (and go to that line)
 
266
 
 
267
  public void find(boolean wrap) {
 
268
    // in case search len is zero,
 
269
    // otherwise replace all will go into an infinite loop
 
270
    found = false;
 
271
 
 
272
    String search = findField.getText();
 
273
    //System.out.println("finding for " + search + " " + findString);
 
274
    // this will catch "find next" being called when no search yet
 
275
    if (search.length() == 0) return;
 
276
 
 
277
    String text = editor.getText();
 
278
 
 
279
    if (ignoreCase) {
 
280
    search = search.toLowerCase();
 
281
      text = text.toLowerCase();
 
282
    }
 
283
 
 
284
    //int selectionStart = editor.textarea.getSelectionStart();
 
285
    int selectionEnd = editor.getSelectionStop();
 
286
 
 
287
    int nextIndex = text.indexOf(search, selectionEnd);
 
288
    if (nextIndex == -1) {
 
289
      if (wrap) {
 
290
        // if wrapping, a second chance is ok, start from beginning
 
291
        nextIndex = text.indexOf(search, 0);
 
292
      }
 
293
 
 
294
      if (nextIndex == -1) {
 
295
        found = false;
 
296
        replaceButton.setEnabled(false);
 
297
        replaceFindButton.setEnabled(false);
 
298
        //Toolkit.getDefaultToolkit().beep();
 
299
        return;
 
300
      }
 
301
    }
 
302
    found = true;
 
303
    replaceButton.setEnabled(true);
 
304
    replaceFindButton.setEnabled(true);
 
305
    editor.setSelection(nextIndex, nextIndex + search.length());
 
306
  }
 
307
 
 
308
 
 
309
  /**
 
310
   * Replace the current selection with whatever's in the
 
311
   * replacement text field.
 
312
   */
 
313
  public void replace() {
 
314
    if (!found) return;  // don't replace if nothing found
 
315
 
 
316
    // check to see if the document has wrapped around
 
317
    // otherwise this will cause an infinite loop
 
318
    String sel = editor.getSelectedText();
 
319
    if (sel.equals(replaceField.getText())) {
 
320
      found = false;
 
321
      replaceButton.setEnabled(false);
 
322
      replaceFindButton.setEnabled(false);
 
323
      return;
 
324
    }
 
325
 
 
326
    editor.setSelectedText(replaceField.getText());
 
327
    //editor.setSketchModified(true);
 
328
    //editor.sketch.setCurrentModified(true);
 
329
    editor.getSketch().setModified(true);  // TODO is this necessary?
 
330
 
 
331
    // don't allow a double replace
 
332
    replaceButton.setEnabled(false);
 
333
    replaceFindButton.setEnabled(false);
 
334
  }
 
335
 
 
336
 
 
337
  /**
 
338
   * Replace everything that matches by doing find and replace
 
339
   * alternately until nothing more found.
 
340
   */
 
341
  public void replaceAll() {
 
342
    // move to the beginning
 
343
    editor.setSelection(0, 0);
 
344
 
 
345
    do {
 
346
      find(false);
 
347
      replace();
 
348
    } while (found);
 
349
  }
 
350
}