1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.support.actions;
14
15 import java.awt.BorderLayout;
16 import java.awt.GridLayout;
17 import java.awt.event.ActionEvent;
18
19 import javax.swing.AbstractAction;
20 import javax.swing.Action;
21 import javax.swing.BorderFactory;
22 import javax.swing.ButtonGroup;
23 import javax.swing.JButton;
24 import javax.swing.JCheckBox;
25 import javax.swing.JComboBox;
26 import javax.swing.JDialog;
27 import javax.swing.JLabel;
28 import javax.swing.JPanel;
29 import javax.swing.JRadioButton;
30
31 import com.eviware.soapui.support.UISupport;
32 import com.eviware.soapui.support.xml.ProxyFindAndReplacable;
33 import com.jgoodies.forms.builder.ButtonBarBuilder;
34
35 /***
36 * Find-and-Replace dialog for a JXmlTextArea
37 *
38 * @author Ole.Matzura
39 */
40
41 public class FindAndReplaceDialog extends AbstractAction
42 {
43 private final ProxyFindAndReplacable target;
44 private JDialog dialog;
45 private JCheckBox caseCheck;
46 private JRadioButton allButton;
47 private JRadioButton selectedLinesButton;
48 private JRadioButton forwardButton;
49 private JRadioButton backwardButton;
50 private JCheckBox wholeWordCheck;
51 private JButton findButton;
52 private JButton replaceButton;
53 private JButton replaceAllButton;
54 private JComboBox findCombo;
55 private JComboBox replaceCombo;
56 private JCheckBox wrapCheck;
57
58 public FindAndReplaceDialog( FindAndReplaceable target )
59 {
60 super( "Find / Replace" );
61 putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "F3" ) );
62 this.target = new ProxyFindAndReplacable( target );
63 }
64
65 public void actionPerformed( ActionEvent e )
66 {
67 show();
68 }
69
70 public void show()
71 {
72 if( dialog == null )
73 buildDialog();
74
75 replaceCombo.setEnabled( target.isEditable() );
76 replaceAllButton.setEnabled( target.isEditable() );
77 replaceButton.setEnabled( target.isEditable() );
78
79 UISupport.showDialog( dialog );
80 findCombo.getEditor().selectAll();
81 findCombo.requestFocus();
82 }
83
84 private void buildDialog()
85 {
86 dialog = new JDialog( UISupport.getMainFrame(), "Find / Replace", false );
87
88 JPanel panel = new JPanel( new BorderLayout() );
89 findCombo = new JComboBox();
90 findCombo.setEditable( true );
91 replaceCombo = new JComboBox();
92 replaceCombo.setEditable( true );
93
94
95 GridLayout gridLayout = new GridLayout( 2, 2 );
96 gridLayout.setVgap( 5 );
97 JPanel inputPanel = new JPanel( gridLayout );
98 inputPanel.add( new JLabel( "Find:" ) );
99 inputPanel.add( findCombo );
100 inputPanel.add( new JLabel( "Replace with:" ) );
101 inputPanel.add( replaceCombo );
102 inputPanel.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
103
104
105 ButtonGroup directionGroup = new ButtonGroup();
106 forwardButton = new JRadioButton( "Forward", true );
107 forwardButton.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
108 directionGroup.add( forwardButton );
109 backwardButton = new JRadioButton( "Backward" );
110 backwardButton.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
111 directionGroup.add( backwardButton );
112
113 JPanel directionPanel = new JPanel( new GridLayout( 2, 1 ) );
114 directionPanel.add( forwardButton );
115 directionPanel.add( backwardButton );
116 directionPanel.setBorder( BorderFactory.createTitledBorder( "Direction" ) );
117
118
119 ButtonGroup scopeGroup = new ButtonGroup();
120 allButton = new JRadioButton( "All", true );
121 allButton.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
122 selectedLinesButton = new JRadioButton( "Selected Lines" );
123 selectedLinesButton.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
124 scopeGroup.add( allButton );
125 scopeGroup.add( selectedLinesButton );
126
127 JPanel scopePanel = new JPanel( new GridLayout( 2, 1 ) );
128 scopePanel.add( allButton );
129 scopePanel.add( selectedLinesButton );
130 scopePanel.setBorder( BorderFactory.createTitledBorder( "Scope" ) );
131
132
133 caseCheck = new JCheckBox( "Case Sensitive" );
134 caseCheck.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
135 wholeWordCheck = new JCheckBox( "Whole Word" );
136 wholeWordCheck.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
137 wrapCheck = new JCheckBox( "Wrap Search" );
138 wrapCheck.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
139 JPanel optionsPanel = new JPanel( new GridLayout( 3, 1 ) );
140 optionsPanel.add( caseCheck );
141 optionsPanel.add( wholeWordCheck );
142 optionsPanel.add( wrapCheck );
143 optionsPanel.setBorder( BorderFactory.createTitledBorder( "Options" ) );
144
145
146 JPanel options = new JPanel( new GridLayout( 1, 2 ) );
147
148 JPanel radios = new JPanel( new GridLayout( 2, 1 ) );
149 radios.add( directionPanel );
150 radios.add( scopePanel );
151
152 options.add( optionsPanel );
153 options.add( radios );
154 options.setBorder( BorderFactory.createEmptyBorder( 0, 8, 0, 8 ) );
155
156
157 ButtonBarBuilder builder = new ButtonBarBuilder();
158 findButton = new JButton( new FindAction() );
159 builder.addFixed( findButton );
160 builder.addRelatedGap();
161 replaceButton = new JButton( new ReplaceAction() );
162 builder.addFixed( replaceButton );
163 builder.addRelatedGap();
164 replaceAllButton = new JButton( new ReplaceAllAction() );
165 builder.addFixed( replaceAllButton );
166 builder.addUnrelatedGap();
167 builder.addFixed( new JButton( new CloseAction() ) );
168 builder.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
169
170
171 panel.add( inputPanel, BorderLayout.NORTH );
172 panel.add( options, BorderLayout.CENTER );
173 panel.add( builder.getPanel(), BorderLayout.SOUTH );
174
175 dialog.getContentPane().add( panel );
176 dialog.pack();
177 UISupport.initDialogActions( dialog, null, findButton );
178 }
179
180 private int findNext( int pos, String txt, String value )
181 {
182 int ix = forwardButton.isSelected() ? txt.indexOf( value, pos ) : txt.lastIndexOf( value, pos );
183
184 if( selectedLinesButton.isSelected() && ( ix < target.getSelectionStart() || ix > target.getSelectionEnd() ) )
185 ix = -1;
186
187 if( wholeWordCheck.isSelected() )
188 {
189 while( ix != -1
190 && ( ( ix > 0 && Character.isLetterOrDigit( txt.charAt( ix - 1 ) ) ) || ( ix < txt.length()
191 - value.length() - 1 && Character.isLetterOrDigit( txt.charAt( ix + value.length() ) ) ) ) )
192 {
193 ix = forwardButton.isSelected() ? ++ix : --ix;
194 ix = forwardButton.isSelected() ? txt.indexOf( value, ix ) : txt.lastIndexOf( value, ix );
195 }
196 }
197
198 if( ix == -1 && wrapCheck.isSelected() )
199 {
200 if( forwardButton.isSelected() && pos > 0 )
201 return findNext( 0, txt, value );
202 else if( backwardButton.isSelected() && pos < txt.length() - 1 )
203 return findNext( txt.length() - 1, txt, value );
204 }
205
206 return ix;
207 }
208
209 private class FindAction extends AbstractAction
210 {
211 String lastSearchedItem = "";
212 int lastPositionF = -1;
213
214 public FindAction()
215 {
216 super( "Find/Find Next" );
217 }
218
219 public void actionPerformed( ActionEvent e )
220 {
221 int pos = tweakPosition();
222 int lastpos = tweakLastPosition();
223
224 String txt = target.getText();
225
226 if( findCombo.getSelectedItem() == null )
227 {
228 return;
229 }
230 String value = findCombo.getSelectedItem().toString();
231 if( value.length() == 0 || ( pos == txt.length() && !wrapCheck.isSelected() ) )
232 return;
233
234 if( !caseCheck.isSelected() )
235 {
236 value = value.toLowerCase();
237 txt = txt.toLowerCase();
238 }
239
240 if( pos == lastPositionF && value.equals( lastSearchedItem ) )
241 if( forwardButton.isSelected() )
242 pos += value.length() + 1;
243 else
244 pos -= value.length() - 1;
245
246 int ix = findNext( pos, txt, value );
247
248 lastSearchedItem = value;
249 lastPositionF = ix;
250
251 if( ix != -1 )
252 {
253 if( selectedLinesButton.isSelected() )
254 {
255 target.select( ix, lastpos );
256 }
257 else
258 {
259 target.select( ix, ix + value.length() );
260 }
261
262 for( int c = 0; c < findCombo.getItemCount(); c++ )
263 {
264 if( findCombo.getItemAt( c ).equals( value ) )
265 {
266 findCombo.removeItem( c );
267 break;
268 }
269 }
270
271 findCombo.insertItemAt( value, 0 );
272 }
273 else
274 {
275 UISupport.showErrorMessage( "String [" + value + "] not found" );
276 }
277 }
278 }
279
280 private class ReplaceAction extends AbstractAction
281 {
282 String lastSearchedItem = "";
283 int lastPositionF = -1;
284
285 public ReplaceAction()
286 {
287 super( "Replace/Replace Next" );
288 }
289
290 public void actionPerformed( ActionEvent e )
291 {
292 int pos = tweakPosition();
293 int lastpos = tweakLastPosition();
294
295 String txt = target.getText();
296
297 if( findCombo.getSelectedItem() == null )
298 {
299 return;
300 }
301 String value = findCombo.getSelectedItem().toString();
302 if( value.length() == 0 || txt.length() == 0 )
303 return;
304
305 String newValue = replaceCombo.getSelectedItem() == null ? "" : replaceCombo.getSelectedItem().toString();
306
307 if( !caseCheck.isSelected() )
308 {
309 if( newValue.equalsIgnoreCase( value ) )
310 return;
311 value = value.toLowerCase();
312 txt = txt.toLowerCase();
313 }
314 else if( newValue.equals( value ) )
315 return;
316
317 if( pos == lastPositionF && value.equals( lastSearchedItem ) )
318 if( forwardButton.isSelected() )
319 pos += value.length() + 1;
320 else
321 pos -= value.length() - 1;
322
323 int ix = findNext( pos, txt, value );
324
325 lastSearchedItem = value;
326 lastPositionF = ix;
327
328 int firstIx = ix;
329 if( ix != -1 )
330 {
331
332
333 target.select( ix, ix + value.length() );
334
335 target.setSelectedText( newValue );
336 if( selectedLinesButton.isSelected() )
337 {
338 target.select( ix, lastpos );
339 }
340 else
341 {
342 target.select( ix, ix + newValue.length() );
343 }
344
345
346 if( ix < firstIx )
347 firstIx += newValue.length() - value.length();
348
349 txt = target.getText();
350 if( !caseCheck.isSelected() )
351 {
352 txt = txt.toLowerCase();
353 }
354
355 if( forwardButton.isSelected() )
356 {
357 ix = findNext( ix + newValue.length(), txt, value );
358 }
359 else
360 {
361 ix = findNext( ix - 1, txt, value );
362 }
363 }
364 else
365 {
366 UISupport.showErrorMessage( "String [" + value + "] not found" );
367 }
368 }
369 }
370
371 private class ReplaceAllAction extends AbstractAction
372 {
373 public ReplaceAllAction()
374 {
375 super( "Replace All" );
376 }
377
378 public void actionPerformed( ActionEvent e )
379 {
380 int pos = tweakPosition();
381 String txt = target.getDialogText();
382
383 if( findCombo.getSelectedItem() == null )
384 {
385 return;
386 }
387 String value = findCombo.getSelectedItem().toString();
388 if( value.length() == 0 || txt.length() == 0 )
389 return;
390
391 String newValue = replaceCombo.getSelectedItem() == null ? "" : replaceCombo.getSelectedItem().toString();
392
393 if( !caseCheck.isSelected() )
394 {
395 if( newValue.equalsIgnoreCase( value ) )
396 return;
397 value = value.toLowerCase();
398 txt = txt.toLowerCase();
399 }
400 else if( newValue.equals( value ) )
401 return;
402
403 int ix = findNext( pos, txt, value );
404 if( ix >= 0 )
405 {
406
407 int firstIx = ix;
408 int valueInNewValueIx = !caseCheck.isSelected() ? newValue.toLowerCase().indexOf( value ) : newValue
409 .indexOf( value );
410
411 target.setReplaceAll( true );
412 target.setSBTarget();
413 target.setNewValue( newValue );
414 while( ix != -1 )
415 {
416 target.select( ix, ix + value.length() );
417 target.setSelectedText( newValue );
418 target.select( ix, ix + newValue.length() );
419
420
421 if( ix < firstIx )
422 firstIx += newValue.length() - value.length();
423
424 txt = target.getText();
425 if( !caseCheck.isSelected() )
426 {
427 txt = txt.toLowerCase();
428 }
429
430 if( forwardButton.isSelected() )
431 {
432 ix = findNext( ix + newValue.length(), txt, value );
433 }
434 else
435 {
436 ix = findNext( ix - 1, txt, value );
437 }
438 if( wrapCheck.isSelected() && valueInNewValueIx != -1 && ix == firstIx + valueInNewValueIx )
439 {
440 break;
441 }
442 }
443 target.flushSBText();
444 target.setReplaceAll( false );
445 target.setCarretPosition( forwardButton.isSelected() );
446 }
447 else
448 {
449 UISupport.showErrorMessage( "String [" + value + "] not found" );
450 }
451 }
452
453 }
454
455 private class CloseAction extends AbstractAction
456 {
457 public CloseAction()
458 {
459 super( "Close" );
460 }
461
462 public void actionPerformed( ActionEvent e )
463 {
464 dialog.setVisible( false );
465 }
466 }
467
468 private int tweakPosition()
469 {
470 int pos = target.getCaretPosition();
471 if( selectedLinesButton.isSelected() )
472 {
473 if( forwardButton.isSelected() )
474 {
475 int selstart = target.getSelectionStart();
476 if( selstart < pos && selstart != -1 )
477 pos = selstart;
478 }
479
480 else
481 {
482 int selend = target.getSelectionEnd();
483 if( selend > pos && selend != -1 )
484 pos = selend;
485 }
486 }
487 else
488 {
489 int selstart = target.getSelectionStart();
490 if( selstart < pos && selstart != -1 )
491 pos = selstart;
492 }
493 return pos;
494 }
495
496 private int tweakLastPosition()
497 {
498 return forwardButton.isSelected() ? target.getSelectionEnd() : target.getSelectionStart();
499 }
500
501 }