Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/port80/eclipse/jdt/actions/RegexFindDialog.java


1   package com.port80.eclipse.jdt.actions;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.apache.oro.text.perl.Perl5Util;
7   import org.eclipse.jface.dialogs.Dialog;
8   import org.eclipse.jface.viewers.AbstractTreeViewer;
9   import org.eclipse.jface.viewers.IBaseLabelProvider;
10  import org.eclipse.jface.viewers.ILabelProvider;
11  import org.eclipse.jface.viewers.ISelection;
12  import org.eclipse.jface.viewers.IStructuredSelection;
13  import org.eclipse.jface.viewers.ITreeContentProvider;
14  import org.eclipse.jface.viewers.LabelProvider;
15  import org.eclipse.jface.viewers.StructuredSelection;
16  import org.eclipse.jface.viewers.TableViewer;
17  import org.eclipse.jface.viewers.Viewer;
18  import org.eclipse.jface.viewers.ViewerSorter;
19  import org.eclipse.swt.SWT;
20  import org.eclipse.swt.events.DisposeEvent;
21  import org.eclipse.swt.events.DisposeListener;
22  import org.eclipse.swt.events.ModifyEvent;
23  import org.eclipse.swt.events.ModifyListener;
24  import org.eclipse.swt.events.MouseAdapter;
25  import org.eclipse.swt.events.MouseEvent;
26  import org.eclipse.swt.events.SelectionAdapter;
27  import org.eclipse.swt.events.SelectionEvent;
28  import org.eclipse.swt.graphics.Color;
29  import org.eclipse.swt.graphics.Font;
30  import org.eclipse.swt.graphics.FontMetrics;
31  import org.eclipse.swt.graphics.GC;
32  import org.eclipse.swt.graphics.Point;
33  import org.eclipse.swt.layout.GridData;
34  import org.eclipse.swt.widgets.Button;
35  import org.eclipse.swt.widgets.Combo;
36  import org.eclipse.swt.widgets.Composite;
37  import org.eclipse.swt.widgets.Control;
38  import org.eclipse.swt.widgets.Display;
39  import org.eclipse.swt.widgets.Label;
40  import org.eclipse.swt.widgets.Shell;
41  import org.eclipse.swt.widgets.Table;
42  import org.eclipse.swt.widgets.TableItem;
43  
44  import com.port80.eclipse.jdt.JdtPlugin;
45  import com.port80.eclipse.jdt.ThemeManager;
46  import com.port80.eclipse.util.UIUtil;
47  import com.port80.util.struct.IntList;
48  
49  /**
50   * @author chrisl
51   *
52   * To change this generated comment edit the template variable "typecomment":
53   * Window>Preferences>Java>Templates.
54   * To enable and disable the creation of type comments go to
55   * Window>Preferences>Java>Code Generation.
56   */
57  public class RegexFindDialog extends Dialog {
58  
59    ////////////////////////////////////////////////////////////////////////
60  
61    private static final String NAME = "RegexFindDialog";
62    private static final boolean DEBUG = false;
63    private static final int MAX_PERSISTENT = 16;
64    private static final int STATUS_PERIOD = 0x01ff;
65    private static final int WIDTH=32;
66  
67    ////////////////////////////////////////////////////////////////////////
68  
69    private static RegexFindDialog fDefault;
70    private static Point fWindowPosition;
71    private static List fPatterns = new ArrayList();
72    private static Perl5Util fReEngine;
73  
74    private Viewer fViewer;
75    private List fElements;
76    private String[] fLabels;
77    private LabelProvider fLabelProvider;
78    private int fStart;
79    private int fFound;
80    private int fAnchor;
81    //
82    private boolean fAbort;
83    private boolean fLoaded;
84    private boolean fError;
85    //
86    private Combo fPattern;
87    private Button fButtonFind;
88    private Button fButtonFindBackward;
89    private Button fButtonSelectAll;
90    private Button fCaseSensitive;
91    private Label fStatus;
92    private Color fColorRed;
93    private Color fColorBlack;
94  
95    ////////////////////////////////////////////////////////////////////////
96  
97    public static RegexFindDialog getDefault(Shell shell, AbstractTreeViewer viewer) {
98      if (fDefault == null || fDefault.getShell() == null || fDefault.getShell().isDisposed()) {
99        fDefault = new RegexFindDialog(shell);
100       fDefault.init(viewer);
101     } else
102       fDefault.init(viewer);
103     return fDefault;
104   }
105 
106   public static RegexFindDialog getDefault(Shell shell, TableViewer viewer) {
107     if (fDefault == null || fDefault.getShell() == null || fDefault.getShell().isDisposed()) {
108       fDefault = new RegexFindDialog(shell);
109       fDefault.init(viewer);
110     } else
111       fDefault.init(viewer);
112     return fDefault;
113   }
114 
115   ////////////////////////////////////////////////////////////////////////
116 
117   /**
118    * Constructor for RegexReplaceDialog.
119    * @param parentShell
120    */
121   private RegexFindDialog(Shell parentShell) {
122     super(parentShell);
123     //
124     setShellStyle(SWT.DIALOG_TRIM);
125     // setBlockOnOpen(true);
126   }
127 
128   ////////////////////////////////////////////////////////////////////////
129 
130   private void init(Viewer viewer) {
131     fViewer = viewer;
132     fReEngine = new Perl5Util();
133     ThemeManager manager = JdtPlugin.getThemeManager();
134     fColorRed = manager.getColor("0xff0000");
135     fColorBlack = manager.getColor("0x000000");
136   }
137 
138   void dispose() {
139     fReEngine = null;
140     fElements = null;
141     fLabels = null;
142   }
143 
144   ////////////////////////////////////////////////////////////////////////
145 
146   void loadCompleted() {
147     if (fAbort) {
148       fError = true;
149       fLoaded = true;
150       actionClose();
151       return;
152     }
153     //
154     if (fElements.size() == 0)
155       fError = true;
156     String message;
157     if (!fError) {
158       fStart = findSelectedElement(fViewer);
159       if (fStart >= 0) {
160         fAnchor = fStart;
161         fFound = fStart;
162       } else {
163         fStart = 0;
164         fAnchor = 0;
165         fFound = -1;
166       }
167       if (DEBUG)
168         System.err.println(
169           NAME
170             + ".init(AbstractTreeViewer): fElements.size()="
171             + fElements.size()
172             + ", fStart="
173             + fStart);
174       message = "OK: " + fElements.size() + " elements loaded";
175       fStatus.setForeground(fColorBlack);
176       fStatus.setText(message);
177       fPattern.setEnabled(true);
178       setEnableActions(fPattern.getText().length() > 0);
179     } else {
180       message = "FAILED: " + fElements.size() + " elements loaded";
181       fStatus.setForeground(fColorRed);
182       fStatus.setText(message);
183       setEnableActions(false);
184     }
185     fLoaded = true;
186   }
187 
188   private int findSelectedElement(Viewer viewer) {
189     ISelection s = viewer.getSelection();
190     if (s instanceof IStructuredSelection) {
191       IStructuredSelection selection = (IStructuredSelection) s;
192       if (selection.size() > 0) {
193         Object a = selection.getFirstElement();
194         for (int i = 0; i < fElements.size(); ++i) {
195           if (a.equals(fElements.get(i)))
196             return i;
197         }
198       }
199     }
200     return -1;
201   }
202 
203   ////////////////////////////////////////////////////////////////////////
204 
205   /**
206    * @see org.eclipse.jface.window.Window#constrainShellSize()
207    */
208   protected void constrainShellSize() {
209     Shell shell = getShell();
210     if (fWindowPosition != null) {
211       System.err.println("Last Window location=" + fWindowPosition);
212       shell.setLocation(fWindowPosition);
213     } else {
214       fWindowPosition = shell.getLocation();
215       shell.setLocation(fWindowPosition.x + 200, fWindowPosition.y - 100);
216     }
217     super.constrainShellSize();
218   }
219 
220   /**
221    * @see org.eclipse.jface.window.Window#createContents(Composite)
222    */
223   protected Control createContents(Composite parent) {
224     Composite top = UIUtil.createBox(parent, 1, 1, true, true, 1, 10, 10, 0, 5, null);
225     createDialogArea(top);
226     createButtonBar(top);
227     setEnableActions(false);
228     return top;
229   }
230 
231   protected Control createDialogArea(Composite parent) {
232     ThemeManager manager = JdtPlugin.getThemeManager();
233     Font boldfont = manager.getFont("Bold");
234     Color lightcolor = manager.getColor("LightBG");
235     String title = JdtPlugin.getString("RegexFind.title");
236     String str_search = JdtPlugin.getString("RegexFind.search") + ": ";
237     getShell().setText(title);
238     getShell().addDisposeListener(new DisposeListener() {
239       public void widgetDisposed(DisposeEvent e) {
240         if (DEBUG)
241           System.err.println(NAME + ": shell disposed.");
242         dispose();
243       }
244     });
245     Composite top = UIUtil.createBox(parent, 1, 1, true, true, 10, 0, 0, 5, 5, true, null);
246     Label label =
247       UIUtil.createGridLabel(
248         top,
249         SWT.RIGHT,
250         str_search,
251         null,
252         null,
253         boldfont,
254         2,
255         3,
256         GridData.FILL,
257         GridData.CENTER,
258         false,
259         false);
260     GC gc = new GC(label);
261     gc.setFont(label.getFont());
262     FontMetrics fm = gc.getFontMetrics();
263     ((GridData) label.getLayoutData()).widthHint = fm.getAverageCharWidth() * WIDTH;
264     fPattern = new Combo(top, SWT.FLAT);
265     fPattern.setLayoutData(UIUtil.alignCell(2, 5, GridData.FILL, GridData.CENTER, true, false));
266     fPattern.setBackground(lightcolor);
267     ((GridData) fPattern.getLayoutData()).widthHint = fm.getAverageCharWidth() * WIDTH;
268     gc.dispose();
269     //
270     fButtonFind = new Button(top, SWT.PUSH);
271     fButtonFind.setLayoutData(UIUtil.fillCell(2, 1, false, false));
272     fButtonFind.setToolTipText("Find Next");
273     fButtonFind.setImage(manager.getImage("DownArrow"));
274     fButtonFind.addMouseListener(new MouseAdapter() {
275       public void mouseDown(MouseEvent e) {
276         actionFind();
277       }
278     });
279     //
280     fButtonFindBackward = new Button(top, SWT.PUSH);
281     fButtonFindBackward.setLayoutData(UIUtil.fillCell(2, 1, false, false));
282     fButtonFindBackward.setToolTipText("Find Previous");
283     fButtonFindBackward.setImage(manager.getImage("UpArrow"));
284     fButtonFindBackward.addMouseListener(new MouseAdapter() {
285       public void mouseDown(MouseEvent e) {
286         actionFindBackward();
287       }
288     });
289     //
290     fStatus = new Label(top, SWT.LEFT);
291     fStatus.setLayoutData(UIUtil.fillCell(3, 6, true, true));
292     ((GridData) fStatus.getLayoutData()).heightHint = fm.getHeight() * 2;
293     //
294     fCaseSensitive = UIUtil.createButton(top, SWT.CHECK, "Case sensitive", null, null);
295     fCaseSensitive.setLayoutData(UIUtil.alignCell(3, 4, GridData.END, GridData.CENTER, false, true));
296     //new Label(top,SWT.LEFT).setLayoutData(UIUtil.fillCell(1,4,false,false));
297     //
298     if (fPatterns.size() > 0) {
299       fPattern.setItems((String[]) fPatterns.toArray(new String[fPatterns.size()]));
300       fPattern.setText((String) fPatterns.get(0));
301     }
302     fPattern.addModifyListener(new ModifyListener() {
303       public void modifyText(ModifyEvent e) {
304         patternChanged(e);
305       }
306     });
307     fPattern.setEnabled(false);
308     //
309     Thread loader = new Thread(new ElementLoader(fViewer), "ElementLoader");
310     loader.start();
311     //
312     return top;
313   }
314 
315   protected Control createButtonBar(Composite parent) {
316     Composite top = UIUtil.createBox(parent, 2, 10, 2, 0, 0, null);
317     Button b;
318     fButtonSelectAll = UIUtil.createButton(top, SWT.CENTER, "Select All", null, null, 2, 1, true, false);
319     fButtonSelectAll.addSelectionListener(new SelectionAdapter() {
320       public void widgetSelected(SelectionEvent e) {
321         actionSelectAll();
322       }
323     });
324     b = UIUtil.createButton(top, SWT.CENTER, "Close", null, null, 2, 1, true, false);
325     b.addSelectionListener(new SelectionAdapter() {
326       public void widgetSelected(SelectionEvent e) {
327         actionClose();
328       }
329     });
330     return top;
331   }
332 
333   ////////////////////////////////////////////////////////////////////////
334 
335   private void setEnableActions(boolean enable) {
336     if (fLabels == null || fLabels.length == 0)
337       enable = false;
338     fButtonFind.setEnabled(enable);
339     fButtonFindBackward.setEnabled(enable);
340     fButtonSelectAll.setEnabled(enable);
341   }
342 
343   private void savePattern(String pat) {
344     if (fPatterns.size() > 0 && pat.equals(fPatterns.get(0)))
345       return;
346     if (fPatterns.size() >= MAX_PERSISTENT)
347       fPatterns.remove(fPatterns.size() - 1);
348     fPatterns.add(0, pat);
349   }
350 
351   private boolean find(String pat, int start) {
352     pat = Util.escapeRegex(pat);
353     pat = "/" + pat + (fCaseSensitive.getSelection() ? "/" : "/i");
354     try {
355       for (int i = start; i < fLabels.length; ++i) {
356         if (fReEngine.match(pat, fLabels[i])) {
357           //
358           fFound = i;
359           fStatus.setForeground(fColorBlack);
360           fStatus.setText("index=" + i);
361           return true;
362         }
363       }
364       fStatus.setForeground(fColorRed);
365       fStatus.setText((DEBUG) ? "Not Found: start=" + start : "Not Found");
366       return false;
367     } catch (Exception e) {
368       fStatus.setForeground(fColorRed);
369       fStatus.setText("ERROR: " + e);
370       return false;
371     }
372   }
373 
374   private boolean findBackward(String pat, int start) {
375     pat = Util.escapeRegex(pat);
376     pat = "/" + pat + (fCaseSensitive.getSelection() ? "/" : "/i");
377     try {
378       for (int i = start; i >= 0; --i) {
379         if (fReEngine.match(pat, fLabels[i])) {
380           //
381           fFound = i;
382           fStatus.setForeground(fColorBlack);
383           fStatus.setText("index=" + i);
384           return true;
385         }
386       }
387       fStatus.setForeground(fColorRed);
388       fStatus.setText((DEBUG) ? "Not Found: start=" + start : "Not Found");
389       return false;
390     } catch (Exception e) {
391       fStatus.setForeground(fColorRed);
392       fStatus.setText("ERROR: " + e);
393       return false;
394     }
395   }
396 
397   private void setSelections(IntList a) {
398     int index;
399     List selections = new ArrayList();
400     for (int i = 0; i < a.size(); ++i) {
401       index = a.get(i);
402       selections.add(fElements.get(index));
403     }
404     if (fViewer instanceof TableViewer) {
405       Table table = ((TableViewer) fViewer).getTable();
406       table.setSelection((TableItem[]) selections.toArray(new TableItem[selections.size()]));
407       table.showSelection();
408     } else {
409       fViewer.setSelection(new StructuredSelection(selections), true);
410     }
411   }
412 
413   private void setSelection(int index) {
414     if (fViewer instanceof TableViewer) {
415       Table table = ((TableViewer) fViewer).getTable();
416       table.setSelection(new TableItem[] {(TableItem) fElements.get(index)});
417       table.showSelection();
418     } else {
419       fViewer.setSelection(new StructuredSelection(fElements.get(index)), true);
420     }
421   }
422 
423   ////////////////////////////////////////////////////////////////////////
424 
425   Label getStatus() {
426     return fStatus;
427   }
428 
429   ////////////////////////////////////////////////////////////////////////
430 
431   void actionClose() {
432     if (!fLoaded) {
433       fAbort = true;
434       return;
435     }
436     fWindowPosition = getShell().getLocation();
437     savePattern(fPattern.getText());
438     okPressed();
439   }
440 
441   void actionSelectAll() {
442     String pat = fPattern.getText();
443     savePattern(pat);
444     if (DEBUG)
445       System.err.println(NAME + ".actionSelectAll(): pattern=" + pat);
446     int start = fFound;
447     IntList a = new IntList();
448     fFound=-1;
449     while (find(pat, fFound+1)) {
450       a.add(fFound);
451     }
452     fFound=start;
453     fStatus.setForeground(fColorBlack);
454     fStatus.setText("Found " + a.size()+" elements.");
455     setSelections(a);
456   }
457 
458   void actionFind() {
459     String pat = fPattern.getText();
460     savePattern(pat);
461     if (DEBUG)
462       System.err.println(NAME + ".actionFind(): pattern=" + pat);
463     int start = fFound + 1;
464     if (fFound < 0)
465       start = 0;
466     if (find(pat, start)) {
467       setSelection(fFound);
468       fAnchor = fFound;
469     } else {
470       getShell().getDisplay().beep();
471       fFound = -1;
472     }
473   }
474 
475   void actionFindBackward() {
476     String pat = fPattern.getText();
477     savePattern(pat);
478     if (DEBUG)
479       System.err.println(NAME + ".actionFindBackward(): pattern=" + pat);
480     int start = fFound - 1;
481     if (fFound < 0)
482       start = fElements.size() - 1;
483     if (findBackward(pat, start)) {
484       setSelection(fFound);
485       fAnchor = fFound;
486     } else {
487       getShell().getDisplay().beep();
488       fFound = -1;
489     }
490   }
491 
492   void patternChanged(ModifyEvent event) {
493     String pat = fPattern.getText();
494     if (pat.length() == 0) {
495       setSelection(fAnchor);
496       return;
497     }
498     if (find(pat, fAnchor)) {
499       setSelection(fFound);
500     } else {
501       setSelection(fAnchor);
502     }
503     setEnableActions(pat.length() > 0);
504   }
505 
506   ////////////////////////////////////////////////////////////////////////
507   // These are used by ElementLoader to load elements in a separate thread.
508 
509   void load(AbstractTreeViewer viewer, IStructuredSelection selection) {
510     ITreeContentProvider provider = (ITreeContentProvider) viewer.getContentProvider();
511     IBaseLabelProvider lp = viewer.getLabelProvider();
512     if (!(lp instanceof ILabelProvider)) {
513       fError = true;
514       return;
515     }
516     Object[] roots;
517     if (selection == null || selection.isEmpty() || selection.size() == 0) {
518       roots = provider.getChildren(viewer.getInput());
519     } else {
520       roots = selection.toArray();
521     }
522     fElements = new ArrayList(100);
523     getElements(viewer, provider, roots, fElements);
524     if (fError)
525       return;
526     fLabels = new String[fElements.size()];
527     ILabelProvider labelprovider = (ILabelProvider) lp;
528     for (int i = 0; i < fLabels.length; ++i) {
529       fLabels[i] = labelprovider.getText(fElements.get(i));
530     }
531   }
532 
533   void load(TableViewer viewer, IStructuredSelection selection) {
534     Object[] items;
535     //    if (selection == null || selection.isEmpty() || selection.size() == 0) {
536     items = viewer.getTable().getItems();
537     //    } else {
538     //      items = selection.toArray();
539     //    }
540     //
541     fElements = new ArrayList(100);
542     fLabels = new String[items.length];
543     for (int i = 0; i < items.length; ++i) {
544       fElements.add(items[i]);
545       fLabels[i] = ((TableItem) items[i]).getText();
546     }
547   }
548 
549   private void getElements(
550     AbstractTreeViewer viewer,
551     ITreeContentProvider provider,
552     Object[] parents,
553     List ret) {
554     if (parents == null || parents.length == 0)
555       return;
556     if (fAbort) {
557       fError = true;
558       return;
559     }
560     ViewerSorter sorter = viewer.getSorter();
561     Object[] children;
562     if (sorter != null) {
563       children = parents;
564       parents = new Object[children.length];
565       System.arraycopy(children, 0, parents, 0, children.length);
566       sorter.sort(viewer, parents);
567     }
568     for (int i = 0; i < parents.length; ++i) {
569       if ((ret.size() & STATUS_PERIOD) == 0) {
570         getShell().getDisplay().asyncExec(new StatusReporter("" + ret.size() + " loaded"));
571         if (fAbort) {
572           fError = true;
573           return;
574         }
575       }
576       ret.add(parents[i]);
577       children = provider.getChildren(parents[i]);
578       getElements(viewer, provider, children, ret);
579     }
580   }
581 
582   ////////////////////////////////////////////////////////////////////////
583 
584   /**
585    * Since TableViewer.getItems() and TableItem.getText() requires to run in the display thread,
586    * table entries are loaded in the contructor for now instead of in the thread.run().
587    */
588   private class ElementLoader implements Runnable {
589     private Viewer fViewer;
590     private IStructuredSelection fSelection;
591     private Display fDisplay;
592     public ElementLoader(Viewer viewer) {
593       fViewer = viewer;
594       fSelection = (IStructuredSelection) fViewer.getSelection();
595       if (!(fViewer instanceof AbstractTreeViewer)) {
596         load((TableViewer) fViewer, fSelection);
597       }
598     }
599     public void run() {
600       if (fViewer instanceof AbstractTreeViewer)
601         load((AbstractTreeViewer) fViewer, fSelection);
602       getShell().getDisplay().asyncExec(new Runnable() {
603         public void run() {
604           loadCompleted();
605         }
606       });
607     }
608 
609   }
610 
611   ////////////////////////////////////////////////////////////////////////
612 
613   private class StatusReporter implements Runnable {
614     private String fMessage;
615     public StatusReporter(String message) {
616       fMessage = message;
617     }
618     public void run() {
619       getStatus().setText(fMessage);
620     }
621   }
622 
623   ////////////////////////////////////////////////////////////////////////
624 
625 }