View Javadoc

1   /*
2    * Fsgrep is a simple Java application which allows a user to
3    * search all files in a directory structure for lines matching
4    * a given pattern.  Its functionality is a combination of the
5    * Unix 'find' and 'grep' utilities.
6    * Visit [http://fsgrep.sourceforge.net/] for more information.
7    * 
8    * Copyright (C) 2003-2006 Murali Krishnan [murali_ca_us@users.sourceforge.net]
9    * 
10   * Fsgrep is free software; you can redistribute it and/or modify
11   * it under the terms of version 2 of the GNU General Public
12   * License as published by the Free Software Foundation.
13   * 
14   * Fsgrep 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 Fsgrep (see the file named LICENSE.txt); if not, write
21   * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22   * Boston, MA  02111-1307  USA
23   */
24  
25  package mk.fsgrep.gui;
26  
27  
28  import java.awt.*;
29  import java.awt.event.*;
30  import java.io.File;
31  import java.util.*;
32  import java.util.regex.PatternSyntaxException;
33  
34  import javax.swing.*;
35  import javax.swing.border.*;
36  import javax.swing.plaf.basic.BasicArrowButton;
37  
38  import mk.fsgrep.Fsgrep;
39  import mk.fsgrep.find.Finder;
40  import mk.fsgrep.find.ScanProfile;
41  import mk.fsgrep.find.SubsetFinder;
42  import mk.fsgrep.util.*;
43  import mk.fsgrep.util.output.NullOutput;
44  import mk.fsgrep.util.output.StringOutput;
45  import mk.fsgrep.util.output.TextAreaOutput;
46  import mk.fsgrep.util.output.TextFieldOutput;
47  import mk.fsgrep.util.thread.RunCallback;
48  import mk.fsgrep.util.thread.ThreadRunner;
49  
50  
51  
52  /***
53   * The principle GUI application class.
54   * 
55   * @author  Murali Krishnan
56   *
57   */
58  public class App implements ItemListener,RunCallback {
59  
60      //------------------------------------------------------------
61      //- Class Variables
62  
63      protected static final int V_SEARCH_ONLY = 0;
64      protected static final int V_SEARCH_REPLACE = 1;
65  
66  
67      //------------------------------------------------------------
68      //- Class Functions
69  
70      protected static JPanel wrapButtons(JButton button1, JButton button2) {
71          ArrayList<JButton> buttons = new ArrayList<JButton>();
72          {
73              buttons.add(button1);
74              buttons.add(button2);
75          }
76  
77          JPanel result = wrapButtons(buttons);
78  
79          return result;
80      }
81  
82  
83      protected static JPanel wrapButtons(Collection<JButton> buttons) {
84          JPanel result = new JPanel(new GridLayout(1, buttons.size()));
85  
86          for (JButton button : buttons) {
87              result.add(button);
88          }
89  
90          return result;
91      }
92  
93  
94      //------------------------------------------------------------
95      //- Instance Variables
96  
97      private Fsgrep _model = null;
98      private JFrame _frame = null;
99      private JTextField _fieldSearch1 = null;
100     private JTextField _fieldSearch2 = null;
101     private JTextField _fieldReplacement = null;
102     private JTextField _fieldNumMatch = null;
103     private JTextField _fieldNumRemain = null;
104     private JTextField _fieldNumFinished = null;
105     private JTextField _fieldNumTotal = null;
106     private JTextField _fieldStatus = null;
107     private JCheckBox _checkCase = null;
108     private JCheckBox _checkComments = null;
109     private JCheckBox _checkFilenames = null;
110     private JCheckBox _checkListFiles = null;
111     private JButton _buttonRescan = null;
112     private JButton _buttonChange = null;
113     private JButton _buttonSearch = null;
114     private JButton _buttonClear = null;
115     private JButton _buttonAbort = null;
116     private JButton _buttonResults = null;
117     private JButton _buttonSelectPattern1 = null;
118     private JButton _buttonSelectPattern2 = null;
119     private JComboBox _profileSelect = null;
120     private JProgressBar _progressBar = null;
121     private JTabbedPane _SearchTypePane = null;
122     private Splash _splash = new Splash();
123     private FilelistDisplay _filelistDisplay = new FilelistDisplay();
124     private ResultDisplay _resultDisplay = null;
125 
126     private ThreadRunner _runner = null;
127     private StringBuffer _reportBuffer = new StringBuffer("No search performed.");
128     private ArrayList<JComponent> _activeComponents = new ArrayList<JComponent>();
129     private RecentProfiles _recentProfiles = new RecentProfiles();
130     private MRUList _recentSearches = new MRUList("recent_search_");
131 
132 
133 
134     //------------------------------------------------------------
135     //- Constructors
136 
137     public App() {
138         _runner = new ThreadRunner("MainSearch", this);
139     }
140 
141 
142     //------------------------------------------------------------
143     //- Accessors
144 
145     public Fsgrep getModel() {return _model;}
146     protected JFrame getFrame() {return _frame;}
147     protected JTextField getFieldSearch1() {return _fieldSearch1;}
148     protected JTextField getFieldSearch2() {return _fieldSearch2;}
149     protected JTextField getFieldReplacement() {return _fieldReplacement;}
150     protected JCheckBox getCheckCase() {return _checkCase;}
151     protected JCheckBox getCheckComments() {return _checkComments;}
152     protected JCheckBox getCheckFilenames() {return _checkFilenames;}
153     protected JCheckBox getCheckListFiles() {return _checkListFiles;}
154     protected JTextField getFieldNumMatch() {return _fieldNumMatch;}
155     protected JTextField getFieldNumRemain() {return _fieldNumRemain;}
156     protected JTextField getFieldNumFinished() {return _fieldNumFinished;}
157     protected JTextField getFieldNumTotal() {return _fieldNumTotal;}
158     protected JTextField getFieldStatus() {return _fieldStatus;}
159     protected JButton getButtonRescan() {return _buttonRescan;}
160     protected JButton getButtonChange() {return _buttonChange;}
161     protected JButton getButtonSearch() {return _buttonSearch;}
162     protected JButton getButtonClear() {return _buttonClear;}
163     protected JButton getButtonAbort() {return _buttonAbort;}
164     protected JButton getButtonResults() {return _buttonResults;}
165     protected JButton getButtonSelectPattern1() {return _buttonSelectPattern1;}
166     protected JButton getButtonSelectPattern2() {return _buttonSelectPattern2;}
167     protected JComboBox getProfileSelect() {return _profileSelect;}
168     protected JProgressBar getProgressBar() {return _progressBar;}
169     protected JTabbedPane getSearchTypePane() {return _SearchTypePane;}
170     protected StringBuffer getReportBuffer() {return _reportBuffer;}
171     protected RecentProfiles getRecentProfiles() {return _recentProfiles;}
172     protected ArrayList<JComponent> getActiveComponents() {return _activeComponents;}
173 
174     protected FilelistDisplay getFilelistDisplay() {return _filelistDisplay;}
175     protected ResultDisplay getResultDisplay() {return _resultDisplay;}
176     protected MRUList getRecentSearches() {return _recentSearches;}
177 
178     protected ThreadRunner getRunner() {return _runner;}
179 
180 
181     //------------------------------------------------------------
182     //- Settors
183 
184     public void setModel(Fsgrep val) {_model=val;}
185     protected void setFrame(JFrame val) {_frame=val;}
186     protected void setFieldSearch1(JTextField val) {_fieldSearch1=val;}
187     protected void setFieldSearch2(JTextField val) {_fieldSearch2=val;}
188     protected void setFieldReplacement(JTextField val) {_fieldReplacement=val;}
189     protected void setCheckCase(JCheckBox val) {_checkCase=val;}
190     protected void setCheckComments(JCheckBox val) {_checkComments=val;}
191     protected void setCheckFilenames(JCheckBox val) {_checkFilenames=val;}
192     protected void setCheckListFiles(JCheckBox val) {_checkListFiles=val;}
193     protected void setFieldNumMatch(JTextField val) {_fieldNumMatch=val;}
194     protected void setFieldNumRemain(JTextField val) {_fieldNumRemain=val;}
195     protected void setFieldNumFinished(JTextField val) {_fieldNumFinished=val;}
196     protected void setFieldNumTotal(JTextField val) {_fieldNumTotal=val;}
197     protected void setFieldStatus(JTextField val) {_fieldStatus=val;}
198     protected void setButtonRescan(JButton val) {_buttonRescan=val;}
199     protected void setButtonChange(JButton val) {_buttonChange=val;}
200     protected void setButtonSearch(JButton val) {_buttonSearch=val;}
201     protected void setButtonClear(JButton val) {_buttonClear=val;}
202     protected void setButtonAbort(JButton val) {_buttonAbort=val;}
203     protected void setButtonResults(JButton val) {_buttonResults=val;}
204     protected void setButtonSelectPattern1(JButton val) {_buttonSelectPattern1=val;}
205     protected void setButtonSelectPattern2(JButton val) {_buttonSelectPattern2=val;}
206     protected void setProfileSelect(JComboBox val) {_profileSelect=val;}
207     protected void setProgressBar(JProgressBar val) {_progressBar=val;}
208     protected void setSearchTypePane(JTabbedPane val) {_SearchTypePane = val;}
209 
210     protected void setResultDisplay(ResultDisplay val) {_resultDisplay=val;}
211 
212 
213     //------------------------------------------------------------
214     //- Delegators
215 
216     protected JTextArea getTextArea() {
217         return getResultDisplay().getTextArea();
218     }
219 
220     protected JTextArea getReportArea() {
221         return getResultDisplay().getReportArea();
222     }
223 
224 
225     //------------------------------------------------------------
226     //- Protected GUI Methods
227 
228     protected void createComponents() {
229         Args args = getModel().getArgs();
230 
231         setFrame(new JFrame("fsgrep " + Fsgrep.VERSION));
232 
233         String argsText = getModel().getArgs().getPattern();
234         String searchText = ("".equals(argsText)) ?
235             getMostRecentSearch() :
236             argsText;
237         setFieldSearch1(new JTextField(searchText, 40));
238         setFieldSearch2(new JTextField(searchText, 40));
239         setFieldReplacement(new JTextField("", 40));
240 
241         setCheckCase(new JCheckBox("ignore case", !args.isCaseSensitive()));
242         setCheckComments(new JCheckBox("ignore comments", !args.isSearchingComments()));
243         setCheckFilenames(new JCheckBox("search file names", args.isSearchFileNames()));
244         setCheckListFiles(new JCheckBox("files with matches", args.isListFileMatches()));
245 
246         setFieldNumMatch(new JTextField("0", 4));
247         getFieldNumMatch().setHorizontalAlignment(JTextField.RIGHT);
248         getFieldNumMatch().setEditable(false);
249 
250         setFieldNumRemain(new JTextField("0", 4));
251         getFieldNumRemain().setHorizontalAlignment(JTextField.RIGHT);
252         getFieldNumRemain().setEditable(false);
253 
254         setFieldNumFinished(new JTextField("0", 4));
255         getFieldNumFinished().setHorizontalAlignment(JTextField.RIGHT);
256         getFieldNumFinished().setEditable(false);
257 
258         setFieldNumTotal(new JTextField("0", 4));
259         getFieldNumTotal().setHorizontalAlignment(JTextField.RIGHT);
260         getFieldNumTotal().setEditable(false);
261 
262         setFieldStatus(new JTextField(""));
263         getFieldStatus().setEditable(false);
264 
265         setButtonRescan(new JButton("Rescan"));
266         setButtonChange(new JButton("New"));
267         setButtonSearch(new JButton("Search"));
268         setButtonClear(new JButton("Clear"));
269         setButtonAbort(new JButton("Abort"));
270         setButtonResults(new JButton("Results"));
271         setButtonSelectPattern1(new BasicArrowButton(SwingConstants.SOUTH));
272         getButtonSelectPattern1().setToolTipText("Select a recent search pattern.");
273         setButtonSelectPattern2(new BasicArrowButton(SwingConstants.SOUTH));
274         getButtonSelectPattern2().setToolTipText("Select a recent search pattern.");
275         getButtonAbort().setEnabled(false);
276 
277         setProfileSelect(new JComboBox());
278 
279         setProgressBar(new JProgressBar());
280 
281         setSearchTypePane(new JTabbedPane());
282 
283         setResultDisplay(new ResultDisplay(this));
284 
285         // Make all the buttons the same size.
286         new CommonSizeSet()
287             .add(getButtonChange())
288             .add(getButtonRescan())
289             .add(getButtonSearch())
290             .add(getButtonClear())
291             .add(getButtonResults())
292             .add(getButtonAbort())
293             .equalize();
294 
295         defineActions();
296     }
297 
298 
299     protected String getMostRecentSearch() {
300         String result = "";
301 
302         if (!getRecentSearches().isEmpty()) {
303             result = getRecentSearches().getFirst();
304         }
305 
306         return result;
307     }
308 
309 
310     protected void defineActions() {
311         getActiveComponents().add(getButtonClear());
312         getActiveComponents().add(getButtonSearch());
313         getActiveComponents().add(getButtonChange());
314         getActiveComponents().add(getButtonRescan());
315         getActiveComponents().add(getFieldSearch1());
316         getActiveComponents().add(getFieldSearch2());
317         getActiveComponents().add(getFieldReplacement());
318         getActiveComponents().add(getCheckCase());
319         getActiveComponents().add(getCheckComments());
320         getActiveComponents().add(getCheckFilenames());
321         getActiveComponents().add(getCheckListFiles());
322         getActiveComponents().add(getProfileSelect());
323 
324         getButtonRescan().addActionListener(new ActionListener() {
325                 public void actionPerformed(ActionEvent aEvent) {
326                     getModel().setAction(Fsgrep.ACTION_RESCAN);
327                     runSearch();
328                 }
329             });
330 
331         getButtonChange().addActionListener(new ActionListener() {
332                 public void actionPerformed(ActionEvent aEvent) {
333                     defineProfileSettings();
334                 }
335             });
336 
337         ActionListener getRecentPattern = new ActionListener() {
338                 public void actionPerformed(ActionEvent aEvent) {
339                     selectRecentSearchPattern();
340                 }
341             };
342         getButtonSelectPattern1().addActionListener(getRecentPattern);
343         getButtonSelectPattern2().addActionListener(getRecentPattern);
344 
345         {
346             ActionListener startSearch = new ActionListener() {
347                     public void actionPerformed(ActionEvent aEvent) {
348                         String pattern = findSearchField().getText();
349                         setSearchText(pattern);
350                         if (pattern.equals("")) {
351                             String title = "No pattern";
352                             String content = "A search could not be performed because no pattern was given.";
353                             JOptionPane.showMessageDialog(getFrame(), content, title, JOptionPane.ERROR_MESSAGE);
354                             getFieldSearch1().grabFocus();
355                         } else {
356                             getRecentSearches().add(pattern);
357                             getRecentSearches().saveData();
358                             performPatternSearch(pattern);
359                         }
360                     }
361                 };
362 
363             getFieldSearch1().addActionListener(startSearch);
364             getFieldReplacement().addActionListener(startSearch);
365             getButtonSearch().addActionListener(startSearch);
366         }
367 
368         getButtonClear().addActionListener(new ActionListener() {
369                 public void actionPerformed(ActionEvent aEvent) {
370                     getFieldReplacement().setText("");
371                     setSearchText("");
372                     findSearchField().grabFocus();
373                 }
374             });
375 
376         getButtonAbort().addActionListener(new ActionListener() {
377                 public void actionPerformed(ActionEvent aEvent) {
378                     abortAction();
379                 }
380             });
381 
382         getButtonResults().addActionListener(new ActionListener() {
383                 public void actionPerformed(ActionEvent aEvent) {
384                     getResultDisplay().reshow();
385                 }
386             });
387 
388         getProfileSelect().addActionListener(new ActionListener() {
389                 public void actionPerformed(ActionEvent aEvent) {
390                     handleProfileSelection();
391                 }
392             });
393 
394         getCheckCase().addItemListener(this);
395         getCheckComments().addItemListener(this);
396         getCheckFilenames().addItemListener(this);
397         getCheckListFiles().addItemListener(this);
398     }
399 
400 
401     protected void initializeModel() {
402         getModel().initialize(new StringOutput(getReportBuffer()),
403                               getModel().getArgs().createFileOutput(),
404                               new NullOutput(),
405                               new TextFieldOutput(getFieldStatus()),
406                               new GuiProgressBar(getProgressBar()));
407 
408         getModel().setMatchCounter(new FieldCounter(getFieldNumMatch()));
409         getModel().setRemainingCounter(new FieldCounter(getFieldNumRemain()));
410         getModel().setFinishedCounter(new FieldCounter(getFieldNumFinished()));
411 
412         getRecentProfiles().readData(getModel());
413         if (getRecentProfiles().isEmpty()) {
414             getRecentProfiles().add(getModel().getFinder().getProfile().createSpecification(), getModel().getFinder());
415         } else {
416             getModel().setFinder(getRecentProfiles().get(getRecentProfiles().getCurrent()));
417         }
418 
419         Iterator<String> iterator = getRecentProfiles().iterator();
420         while (iterator.hasNext()) {
421             String spec = iterator.next();
422             getProfileSelect().addItem(spec);
423 
424             getRecentProfiles().get(spec).setFileCount(new FieldCounter(getFieldNumTotal()));
425         }
426     }
427 
428 
429     protected void makeFrame() {
430         getFrame().setJMenuBar(makeMenuBar());
431 
432         getFrame().getContentPane().setLayout(new GridBagLayout());
433         GridBagConstraints gbc = new GridBagConstraints();
434 
435         gbc.anchor = GridBagConstraints.NORTH;
436         gbc.ipadx = 4;
437         gbc.ipady = 4;
438         gbc.fill = GridBagConstraints.HORIZONTAL;
439         gbc.gridx = 0;
440         gbc.weightx = 1;
441         gbc.weighty = 0;
442 
443         gbc.gridy = 0;
444         getFrame().getContentPane().add(makeScanPanel(), gbc);
445 
446         gbc.gridy++;
447         getFrame().getContentPane().add(makeSearchPanel(), gbc);
448 
449         gbc.gridy++;
450         getFrame().getContentPane().add(makeStatusPanel(), gbc);
451 
452         gbc.gridy++;
453         gbc.weighty = 0;
454         getFrame().getContentPane().add(makeStatusBarPanel(), gbc);
455 
456         getFrame().addWindowListener(new WindowAdapter() {
457             public void windowClosing(WindowEvent e) {
458                 OutputRedirector.getInstance().restore();
459                 System.out.println("Exiting fsgrep.");
460                 System.exit(0);
461             }
462         });
463 
464         getFrame().pack();
465         getFrame().setLocation(50, 50);
466     }
467 
468 
469     protected JMenuBar makeMenuBar() {
470         JMenuBar result = new JMenuBar();
471 
472         JMenu mFile = new JMenu("File");
473         {
474             JMenuItem itemProfile = new JMenuItem("New Scan Profile");
475             itemProfile.addActionListener(new ActionListener() {
476                     public void actionPerformed(ActionEvent aEvent) {
477                         defineProfileSettings();
478                     }
479                 });
480             itemProfile.setAccelerator(KeyStroke.getKeyStroke('S', KeyEvent.CTRL_MASK));
481             mFile.add(itemProfile);
482 
483             mFile.addSeparator();
484 
485             JMenuItem itemExit = new JMenuItem("Exit");
486             itemExit.setAccelerator(KeyStroke.getKeyStroke('Q', KeyEvent.CTRL_MASK));
487             ActionListener listener = new ActionListener() {
488                     public void actionPerformed(ActionEvent aEvent) {
489                         WindowEvent wEvent = new WindowEvent(getFrame(), WindowEvent.WINDOW_CLOSING);
490                         getFrame().dispatchEvent(wEvent);
491                     }
492                 };
493             itemExit.addActionListener(listener);
494             mFile.add(itemExit);
495         }
496         result.add(mFile);
497 
498         JMenu mTools = new JMenu("Tools");
499         {
500             JMenuItem itemFileList = new JMenuItem("Show Search Files");
501             {
502                 itemFileList.addActionListener(new ActionListener() {
503                         public void actionPerformed(ActionEvent aEvent) {
504                             getModel().setAction(Fsgrep.ACTION_LISTFILES);
505                             getModel().setLiveOutput(getFilelistDisplay().getOutput());
506                             getFilelistDisplay().clearText();
507                             getFilelistDisplay().setVisible(true);
508                             runSearch();
509                         }
510                     });
511             }
512 
513             JMenuItem itemPreferences = new JMenuItem("Preferences");
514             {
515                 final App app = this;
516                 itemPreferences.addActionListener(new ActionListener() {
517                         public void actionPerformed(ActionEvent aEvent) {
518                             //noinspection UnusedDeclaration
519                             Preferences prefs = new Preferences(app);
520                         }
521                     });
522                 itemPreferences.setAccelerator(KeyStroke.getKeyStroke('P', KeyEvent.CTRL_MASK));
523             }
524 
525             JMenuItem itemClearHistory = new JMenuItem("Clear History");
526             {
527                 itemClearHistory.addActionListener(new ActionListener() {
528                         public void actionPerformed(ActionEvent aEvent) {
529                             clearHistory();
530                         }
531                     });
532             }
533 
534             mTools.add(itemFileList);
535             mTools.add(itemPreferences);
536             mTools.add(itemClearHistory);
537         }
538         result.add(mTools);
539 
540         JMenu mHelp = new JMenu("Help");
541         {
542             JMenuItem itemAbout = new JMenuItem("About");
543             final String title = "About Fsgrep " + Fsgrep.VERSION;
544             final String content = "Fsgrep " + Fsgrep.VERSION + ", " + Fsgrep.MANIFEST_PROPS.getBuildTime() + "\n\n" +
545                 Fsgrep.README;
546             ActionListener listener = new ActionListener() {
547                     public void actionPerformed(ActionEvent aEvent) {
548                         new InfoDialog(getFrame(), title, content);
549                     }
550                 };
551             itemAbout.addActionListener(listener);
552             mHelp.add(itemAbout);
553 
554             if (Fsgrep.DEBUG) {
555                 JMenuItem itemDebug = new JMenuItem("Debug");
556                 itemDebug.addActionListener(new ActionListener() {
557                         public void actionPerformed(ActionEvent aEvent) {
558                             new InfoDialog(getFrame(), "Debug", "Debug action");
559                         }
560                     });
561                 mHelp.addSeparator();
562                 mHelp.add(itemDebug);
563             }
564         }
565         result.add(mHelp);
566 
567         return result;
568     }
569 
570 
571     protected JPanel makeScanPanel() {
572         GridBagConstraints gbc = new GridBagConstraints();
573         gbc.anchor = GridBagConstraints.NORTH;
574         gbc.ipadx = 4;
575         gbc.ipady = 4;
576         gbc.insets = new Insets(2, 4, 2, 4);
577         gbc.fill = GridBagConstraints.HORIZONTAL;
578         gbc.gridx = 0;
579         gbc.gridy = 0;
580         gbc.weightx = 0;
581         gbc.weighty = 1;
582 
583         JPanel result = new JPanel(new GridBagLayout());
584 
585         result.setBorder(BorderFactory.createTitledBorder("File Selection"));
586 
587         result.add(new JLabel("Profile:"), gbc);
588 
589         gbc.gridx = 1;
590         gbc.weightx = 1;
591         result.add(getProfileSelect(), gbc);
592 
593         gbc.gridy = 2;
594         gbc.gridx = 1;
595         gbc.weightx = 0;
596         gbc.anchor = GridBagConstraints.EAST;
597         gbc.fill = GridBagConstraints.NONE;
598         result.add(wrapButtons(getButtonChange(), getButtonRescan()), gbc);
599 
600         return result;
601     }
602 
603 
604     protected JPanel makeSearchPanel() {
605         GridBagConstraints gbc = new GridBagConstraints();
606         gbc.anchor = GridBagConstraints.NORTH;
607         gbc.ipadx = 4;
608         gbc.ipady = 4;
609         gbc.insets = new Insets(2, 4, 2, 4);
610         gbc.fill = GridBagConstraints.HORIZONTAL;
611         gbc.gridx = 0;
612         gbc.gridy = 0;
613         gbc.weightx = 0;
614         gbc.weighty = 1;
615 
616         JPanel result = new JPanel(new GridBagLayout());
617 
618         result.setBorder(BorderFactory.createTitledBorder("Search"));
619 
620         gbc.gridwidth = GridBagConstraints.REMAINDER;
621         result.add(makeSearchEntryPanel(), gbc);
622 
623         gbc.gridy++;
624         gbc.gridx = 0;
625         gbc.gridwidth = 1;
626         gbc.weightx = 0;
627         result.add(new JLabel(""), gbc);
628 
629         gbc.gridx = 1;
630         result.add(getCheckCase(), gbc);
631 
632         gbc.gridx = 2;
633         result.add(new JLabel(""), gbc);
634 
635         gbc.gridx = 3;
636         gbc.weightx = 1;
637         gbc.anchor = GridBagConstraints.EAST;
638         gbc.fill = GridBagConstraints.NONE;
639         result.add(wrapButtons(getButtonSearch(), getButtonClear()), gbc);
640 
641         return result;
642     }
643 
644 
645     protected JTabbedPane makeSearchEntryPanel() {
646         JTabbedPane result = getSearchTypePane();
647 
648         {
649             GridBagConstraints gbc = new GridBagConstraints();
650             gbc.anchor = GridBagConstraints.NORTH;
651             gbc.ipadx = 4;
652             gbc.ipady = 4;
653             gbc.insets = new Insets(2, 4, 2, 4);
654             gbc.fill = GridBagConstraints.HORIZONTAL;
655             gbc.gridx = 0;
656             gbc.gridy = 0;
657             gbc.weightx = 0;
658             gbc.weighty = 1;
659 
660             JPanel panel = new JPanel(new GridBagLayout());
661 
662             gbc.weightx = 0;
663             panel.add(new JLabel("Pattern:"), gbc);
664 
665             gbc.gridx = 1;
666             gbc.gridwidth = GridBagConstraints.REMAINDER;
667             gbc.weightx = 1;
668             panel.add(makePatternField1(), gbc);
669 
670             gbc.gridwidth = 1;
671             gbc.gridheight = 1;
672             gbc.gridy++;
673             gbc.gridx = 0;
674             gbc.weightx = 0;
675             panel.add(new JLabel(""), gbc);
676 
677             gbc.gridx = 1;
678             panel.add(getCheckComments(), gbc);
679 
680             gbc.gridx = 2;
681             panel.add(getCheckFilenames(), gbc);
682 
683             gbc.gridx = 3;
684             gbc.gridwidth = GridBagConstraints.REMAINDER;
685             gbc.weightx = 1;
686             panel.add(getCheckListFiles(), gbc);
687 
688             result.addTab("search only", panel);
689         }
690 
691         {
692             GridBagConstraints gbc = new GridBagConstraints();
693             gbc.anchor = GridBagConstraints.NORTH;
694             gbc.ipadx = 4;
695             gbc.ipady = 4;
696             gbc.insets = new Insets(2, 4, 2, 4);
697             gbc.fill = GridBagConstraints.HORIZONTAL;
698             gbc.gridx = 0;
699             gbc.gridy = 0;
700             gbc.weightx = 0;
701             gbc.weighty = 1;
702 
703             JPanel panel = new JPanel(new GridBagLayout());
704 
705             gbc.weightx = 0;
706             panel.add(new JLabel("Pattern:"), gbc);
707 
708             gbc.gridx = 1;
709             gbc.gridwidth = GridBagConstraints.REMAINDER;
710             gbc.weightx = 1;
711             panel.add(makePatternField2(), gbc);
712 
713             gbc.gridwidth = 1;
714             gbc.gridheight = 1;
715             gbc.gridy++;
716             gbc.gridx = 0;
717             gbc.weightx = 0;
718             panel.add(new JLabel("Replace:"), gbc);
719 
720             gbc.gridx = 1;
721             gbc.gridwidth = GridBagConstraints.REMAINDER;
722             gbc.weightx = 1;
723             panel.add(getFieldReplacement(), gbc);
724 
725 
726             result.addTab("search and replace", panel);
727         }
728 
729         return result;
730     }
731 
732 
733     protected JPanel makePatternField1() {
734         JPanel result = new JPanel(new BorderLayout());
735 
736         result.add(getFieldSearch1(), BorderLayout.CENTER);
737         result.add(getButtonSelectPattern1(), BorderLayout.EAST);
738 
739         return result;
740     }
741 
742 
743     protected JPanel makePatternField2() {
744         JPanel result = new JPanel(new BorderLayout());
745 
746         result.add(getFieldSearch2(), BorderLayout.CENTER);
747         result.add(getButtonSelectPattern2(), BorderLayout.EAST);
748 
749         return result;
750     }
751 
752 
753     protected JPanel makeStatusPanel() {
754         JPanel result = new JPanel(new BorderLayout());
755 
756         result.setBorder(BorderFactory.createTitledBorder("Status"));
757 
758         result.add(getProgressBar(), BorderLayout.SOUTH);
759 
760         GridBagConstraints gbc = new GridBagConstraints();
761         gbc.ipadx = 4;
762         gbc.ipady = 4;
763         gbc.insets = new Insets(2, 4, 2, 4);
764         gbc.fill = GridBagConstraints.HORIZONTAL;
765         gbc.gridx = 0;
766         gbc.gridy = 0;
767         gbc.weightx = 0;
768         gbc.weighty = 1;
769 
770         JPanel fieldPanel = new JPanel(new GridBagLayout());
771         {
772             JPanel leftPanel = new JPanel();
773             {
774                 leftPanel.add(new JLabel("Number of matches:"));
775                 leftPanel.add(getFieldNumMatch());
776             }
777             gbc.anchor = GridBagConstraints.WEST;
778             fieldPanel.add(leftPanel, gbc);
779 
780             JPanel centerPanel = new JPanel();
781             {
782                 centerPanel.add(new JLabel("Files remaining/finished/total:"));
783                 centerPanel.add(getFieldNumRemain());
784                 centerPanel.add(getFieldNumFinished());
785                 centerPanel.add(getFieldNumTotal());
786             }
787             gbc.anchor = GridBagConstraints.EAST;
788             gbc.fill = GridBagConstraints.NONE;
789             gbc.weightx = 1;
790             gbc.gridx = 1;
791             fieldPanel.add(centerPanel, gbc);
792 
793             JPanel buttonPanel = wrapButtons(getButtonResults(), getButtonAbort());
794             gbc.gridy = 1;
795             gbc.gridx = 1;
796             fieldPanel.add(buttonPanel, gbc);
797         }
798         result.add(fieldPanel, BorderLayout.CENTER);
799 
800         return result;
801     }
802 
803 
804     protected JPanel makeStatusBarPanel() {
805         JPanel result = new JPanel(new BorderLayout());
806 
807         Border border = BorderFactory.createBevelBorder(BevelBorder.RAISED);
808         result.setBorder(border);
809 
810         result.add(getFieldStatus(), BorderLayout.CENTER);
811 
812         return result;
813     }
814 
815 
816     //------------------------------------------------------------
817     //- Protected Action Handling
818 
819     protected void closeSplash() {
820         if (_splash != null) {
821             _splash.dispose();
822         }
823     }
824 
825 
826     protected void performPatternSearch(String pattern) {
827         try {
828             getResultDisplay().clear();
829 
830             setupAction(pattern);
831             runSearch();
832         } catch (PatternSyntaxException rese) {
833             String title = "Pattern Error";
834             String content = "'" + pattern + "'\n" + rese.getMessage();
835             JOptionPane.showMessageDialog(getFrame(), content, title, JOptionPane.ERROR_MESSAGE);
836         }
837     }
838 
839 
840     protected void performRefinedSearch(String newPattern, Collection<TargetFile> files) {
841         SubsetFinder finder = new SubsetFinder(files);
842         getModel().useTransientFinder(finder);
843         performPatternSearch(newPattern);
844     }
845 
846 
847     protected void defineProfileSettings() {
848         //noinspection UnusedDeclaration
849         ProfileSettings settings = new ProfileSettings(this);
850         getFieldSearch1().grabFocus();
851     }
852 
853 
854     protected void selectRecentSearchPattern() {
855         if (getRecentSearches().isEmpty()) {
856             getFieldStatus().setText("No recent search patterns.");
857         } else {
858             //noinspection UnusedDeclaration
859             RecentPatternSelector rps = new RecentPatternSelector(this);
860         }
861     }
862 
863 
864     /***
865      * The callback function for the profile selection dialog.
866      *
867      * @param dir  The base directory to scan.
868      * @param suffix  The file suffix for which to scan.
869      */
870     protected void handleProfileSettings(String dir, String suffix) {
871         ScanProfile profile = new ScanProfile(new File(dir), suffix);
872         String spec = profile.createSpecification();
873 
874         Finder finder = getRecentProfiles().contains(spec) ?
875             getRecentProfiles().get(spec) :
876             new Finder(getModel(), profile);
877         finder.setFileCount(new FieldCounter(getFieldNumTotal()));
878         getRecentProfiles().add(spec, finder);
879 
880         setProfileSelection(spec);
881 
882         handleNewProfileSelection(false);
883     }
884 
885 
886     /***
887      * The action handler for the profile section list.
888      * 
889      */
890     protected void handleProfileSelection() {
891         String selected = String.valueOf(getProfileSelect().getSelectedItem());
892 
893         // Only operate if a different selection was made.
894         if (!selected.equals(getRecentProfiles().getCurrent())) {
895             handleNewProfileSelection(true);
896         }
897     }
898 
899 
900     protected void handleNewProfileSelection(boolean setSelection) {
901         String selected = String.valueOf(getProfileSelect().getSelectedItem());
902         getRecentProfiles().select(selected);
903         Finder finder = getRecentProfiles().get(selected);
904         getModel().setFinder(finder);
905 
906         if (setSelection) {
907             setProfileSelection(selected);
908         }
909 
910         String total = String.valueOf(finder.getFileList().size());
911         getFieldNumTotal().setText(total);
912         getFieldNumFinished().setText("0");
913         getFieldNumRemain().setText("0");
914         getFieldNumMatch().setText("0");
915         getResultDisplay().clear();
916     }
917 
918 
919     protected void setProfileSelection(String entry) {
920         getProfileSelect().removeItem(entry);
921         getProfileSelect().insertItemAt(entry, 0);
922         getProfileSelect().setSelectedIndex(0);
923     }
924 
925 
926     protected void showSearchStatisticsReport() {
927         String content = getReportBuffer().toString();
928         getResultDisplay().getReportArea().setText(content);
929     }
930 
931 
932     protected void clearSearchStatisticsReport() {
933         int end = getReportBuffer().length();
934         getReportBuffer().delete(0, end);
935     }
936 
937 
938     protected void runSearch() {
939         clearSearchStatisticsReport();
940 
941         getButtonAbort().setEnabled(true);
942         for (JComponent component : getActiveComponents()) {
943             component.setEnabled(false);
944         }
945         getFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
946 
947         getFieldStatus().setText("Search started ...");
948 
949         getRunner().execute(getModel());
950     }
951 
952 
953     protected void formatResults() {
954         getFieldStatus().setText("Formatting ...");
955 
956         getResultDisplay().defineResults(getModel().getResultList());
957     }
958 
959 
960     protected void abortAction() {
961         getModel().setAborted(true);
962     }
963 
964 
965     protected void clearHistory() {
966         // Clear the recent search patterns.
967         getRecentSearches().keepFirst();
968         getRecentSearches().saveData();
969 
970         // Clear the recent scan profiles.
971         getRecentProfiles().keepFirst();
972         int numToRemove = getProfileSelect().getItemCount() - 1;
973         for (int i = 0; i < numToRemove; i++) {
974             getProfileSelect().removeItemAt(1);
975         }
976     }
977 
978 
979     protected int findSearchType() {
980         int result = getSearchTypePane().getSelectedIndex();
981         return result;
982     }
983 
984     protected JTextField findSearchField() {
985         JTextField result = getFieldSearch1();
986 
987         if (V_SEARCH_REPLACE == findSearchType()) {
988             result = getFieldSearch2();
989         }
990 
991         return result;
992     }
993 
994     protected JButton findButtonSelectPattern() {
995         JButton result = getButtonSelectPattern1();
996 
997         if (V_SEARCH_REPLACE == findSearchType()) {
998             result = getButtonSelectPattern2();
999         }
1000 
1001         return result;
1002     }
1003 
1004 
1005     protected void setupAction(String pattern) {
1006 
1007         getModel().setPattern(pattern);
1008         getModel().setLiveOutput(new TextAreaOutput(getTextArea()));
1009 
1010         if (V_SEARCH_REPLACE == findSearchType()) {
1011             getModel().setAction(Fsgrep.ACTION_REPLACE);
1012             getModel().setReplacement(getFieldReplacement().getText());
1013         } else {            
1014             getModel().setAction(Fsgrep.ACTION_SEARCH);
1015         }
1016     }
1017 
1018 
1019     protected void setSearchText(String string) {
1020         getFieldSearch1().setText(string);
1021         getFieldSearch2().setText(string);
1022     }
1023 
1024 
1025     //------------------------------------------------------------
1026     //- Public Interface Functions
1027 
1028     public void launch(Fsgrep fsgrep) {
1029         setModel(fsgrep);
1030 
1031         createComponents();
1032         initializeModel();
1033         makeFrame();
1034 
1035         getFrame().setVisible(true);
1036         closeSplash();
1037 
1038         getFieldSearch1().grabFocus();
1039     }
1040 
1041 
1042 
1043     //------------------------------------------------------------
1044     //- Class Interface Functions
1045 
1046     public void itemStateChanged(ItemEvent ie) {
1047         Object source = ie.getItemSelectable();
1048         boolean value = (ie.getStateChange() == ItemEvent.SELECTED);
1049         Args args = getModel().getArgs();
1050 
1051         if (source == getCheckCase()) {
1052             args.setCaseSensitive(!value);
1053         } else if (source == getCheckComments()) {
1054             args.setSearchingComments(!value);
1055         } else if (source == getCheckFilenames()) {
1056             args.setSearchFileNames(value);
1057         } else if (source == getCheckListFiles()) {
1058             args.setListFileMatches(value);
1059         }
1060     }
1061 
1062 
1063     public void runFinished(ThreadRunner runner) {
1064         getButtonAbort().setEnabled(false);
1065         for (JComponent component : getActiveComponents()) {
1066             component.setEnabled(true);
1067         }
1068         getFrame().setCursor(Cursor.getDefaultCursor());
1069 
1070         if (getModel().isActionSearch()) {
1071             formatResults();
1072         }
1073         showSearchStatisticsReport();
1074 
1075         String statusText = getModel().isAborted() ?
1076             "Finished (premature abort)." :
1077             "Finished.";
1078         getFieldStatus().setText(statusText);
1079 
1080         findSearchField().grabFocus();
1081 
1082         if (getModel().isActionSearch()) {
1083             getResultDisplay().reshow();
1084         }
1085 
1086         getModel().setAction(Fsgrep.ACTION_UNDEFINED);  // Reset.
1087     }
1088 
1089 
1090     //------------------------------------------------------------
1091     //- Inner Classes
1092 
1093 
1094 
1095     //------------------------------------------------------------
1096     //- Main
1097 
1098 
1099 
1100 }