View Javadoc

1   /*
2    * $Id: FilterFilesPanel.java,v 1.27 2008/01/14 21:23:24 edankert Exp $
3    *
4    * The contents of this file are subject to the Mozilla Public License 
5    * Version 1.1 (the "License"); you may not use this file except in 
6    * compliance with the License. You may obtain a copy of the License at 
7    * http://www.mozilla.org/MPL/ 
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis, 
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
11   * for the specific language governing rights and limitations under the License.
12   *
13   * The Original Code is XML Hammer code. (org.xmlhammer.*)
14   *
15   * The Initial Developer of the Original Code is Edwin Dankert. Portions created 
16   * by the Initial Developer are Copyright (C) 2005 - 2006 the Initial Developer. 
17   * All Rights Reserved.
18   *
19   * Contributor(s): Edwin Dankert <edankert@gmail.com>
20   */
21  
22  package org.xmlhammer.gui.input;
23  
24  import java.awt.BorderLayout;
25  import java.awt.Component;
26  import java.awt.Dimension;
27  import java.awt.FlowLayout;
28  import java.awt.Font;
29  import java.awt.event.ActionEvent;
30  import java.awt.event.ActionListener;
31  import java.awt.event.ItemEvent;
32  import java.awt.event.ItemListener;
33  import java.io.File;
34  import java.net.URI;
35  import java.util.ArrayList;
36  import java.util.regex.Pattern;
37  
38  import javax.swing.Box;
39  import javax.swing.Icon;
40  import javax.swing.ImageIcon;
41  import javax.swing.JButton;
42  import javax.swing.JCheckBox;
43  import javax.swing.JComboBox;
44  import javax.swing.JFileChooser;
45  import javax.swing.JLabel;
46  import javax.swing.JPanel;
47  import javax.swing.JSeparator;
48  import javax.swing.JTextField;
49  import javax.swing.border.EmptyBorder;
50  import javax.swing.event.DocumentEvent;
51  import javax.swing.event.DocumentListener;
52  
53  import org.bounce.FormConstraints;
54  import org.bounce.FormLayout;
55  import org.bounce.image.ImageLoader;
56  import org.bounce.util.URIUtils;
57  import org.xmlhammer.gui.history.HistoryComboBox;
58  import org.xmlhammer.gui.history.HistoryComboBoxModel;
59  import org.xmlhammer.gui.history.HistoryUtilities;
60  import org.xmlhammer.gui.overview.CheckBoxNode;
61  import org.xmlhammer.gui.overview.OverviewNode;
62  import org.xmlhammer.gui.overview.OverviewTreeModel;
63  import org.xmlhammer.gui.util.BrowseButton;
64  import org.xmlhammer.gui.util.UndoableCheckBoxItemListener;
65  import org.xmlhammer.model.project.Filter;
66  
67  /***
68   * Filter Files by wilcard or regular expression.
69   * 
70   * @version $Revision: 1.27 $, $Date: 2008/01/14 21:23:24 $
71   * @author Edwin Dankert <edankert@gmail.com>
72   */
73  
74  public class FilterFilesPanel extends JPanel {
75  	private static final long serialVersionUID = 3257852090755134776L;
76  
77      private static final ImageIcon TEXT_FIELD_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/elcl16/textfield_obj.gif");
78      private static final ImageIcon ERROR_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/obj16/error_obj.gif");
79  
80      private static final ImageIcon HOME_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/elcl16/home_nav.gif");
81      private static final ImageIcon UP_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/elcl16/prev_nav.gif");
82  
83      private ArrayList<OverviewNode> nodes   = null;
84  
85      private JFileChooser chooser 			= null;
86  	private HistoryComboBox lookInField 	= null;
87      private DirectoryNode lookInNode        = null;
88      private JLabel lookInErrorLabel        = null;
89  
90      private JCheckBox regexCheck		 	= null;
91  	private JCheckBox subdirCheck		 	= null;
92  	private HistoryComboBox patternField	= null;
93  
94      private HistoryComboBox storeInField    = null;
95      private DirectoryNode storeInNode        = null;
96      private JLabel storeInErrorLabel        = null;
97  //  private JCheckBox flattenCheck          = null;
98      private HistoryComboBox extensionField  = null;
99      private PatternNode patternNode         = null;
100     private JLabel patternErrorLabel        = null;
101 
102     public FilterFilesPanel(InputPage parent) {
103         this(parent, false);
104     }
105 
106     /***
107 	 * Constructs a new Input Panel.
108 	 */
109 	public FilterFilesPanel(InputPage parent, boolean resultEnabled) {
110 		super( new FormLayout( 11, 5));
111 		
112 		setBorder( new EmptyBorder( 10, 10, 10, 10));
113 		
114 		chooser = new JFileChooser();
115 		chooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY);
116 		
117 		JButton dummyBrowseButton = new BrowseButton();
118 
119         lookInField = new HistoryComboBox(parent, new HistoryComboBoxModel(HistoryUtilities.getInstance().getDirectories()));
120 		lookInField.setPreferredSize(new Dimension( lookInField.getPreferredSize().width, dummyBrowseButton.getPreferredSize().height));
121         ((JTextField)lookInField.getEditor().getEditorComponent()).getDocument().addDocumentListener(new DocumentListener() {
122             public void insertUpdate(DocumentEvent arg0) {
123                 checkField(lookInErrorLabel, lookInNode, lookInField);
124             }
125 
126             public void removeUpdate(DocumentEvent arg0) {
127                 checkField(lookInErrorLabel, lookInNode, lookInField);
128             }
129 
130             public void changedUpdate(DocumentEvent arg0) {}
131         });
132         
133         if (parent != null) {
134             parent.getProjectView().getFieldManager().addField( lookInField);
135         }
136 
137         DirectorySelectionPanel lookInPanel = new DirectorySelectionPanel(lookInField);
138 		
139         lookInErrorLabel = new JLabel(ERROR_ICON);
140         lookInErrorLabel.setVisible(false);
141         lookInErrorLabel.setBorder(new EmptyBorder(2, 0, 0, 0));
142         lookInErrorLabel.setHorizontalAlignment(JLabel.LEFT);
143         
144         JPanel lookInErrorPanel = new JPanel(new FormLayout());
145         lookInErrorPanel.add(lookInPanel, FormLayout.FULL_FILL);
146         lookInErrorPanel.add(lookInErrorLabel, FormLayout.FULL_FILL);
147 
148         JLabel lookInLabel = new JLabel("Look in:");
149         lookInLabel.setPreferredSize(new Dimension(lookInLabel.getPreferredSize().width, lookInPanel.getPreferredSize().height));
150         add(lookInLabel, new FormConstraints( FormConstraints.LEFT, FormConstraints.RIGHT, FormConstraints.TOP));
151 		add(lookInErrorPanel, FormLayout.RIGHT_FILL);
152 
153 		add( new JLabel(), FormLayout.LEFT);
154 		subdirCheck = new JCheckBox( "Include Subdirectories");
155         
156         if (parent != null) {
157             parent.getProjectView().getFieldManager().addField( subdirCheck );
158         }
159 		
160         add( subdirCheck, FormLayout.RIGHT);
161         subdirCheck.addItemListener(new UndoableCheckBoxItemListener(parent, subdirCheck));
162 
163 		patternField = new HistoryComboBox(parent, new HistoryComboBoxModel(HistoryUtilities.getInstance().getPatterns()));
164 		patternField.setFont( patternField.getFont().deriveFont( Font.PLAIN));
165 		patternField.setPreferredSize( new Dimension( patternField.getPreferredSize().width, dummyBrowseButton.getPreferredSize().height));
166         ((JTextField)patternField.getEditor().getEditorComponent()).getDocument().addDocumentListener(new DocumentListener() {
167             public void insertUpdate(DocumentEvent arg0) {
168                 checkPattern();
169             }
170 
171             public void removeUpdate(DocumentEvent arg0) {
172                 checkPattern();
173             }
174 
175             public void changedUpdate(DocumentEvent arg0) {}
176         });
177         if (parent != null) {
178             parent.getProjectView().getFieldManager().addField( patternField);
179         }
180         
181 		add( Box.createVerticalStrut(10), FormLayout.FULL);
182 
183 		JLabel filler = new JLabel();
184 		filler.setPreferredSize( new Dimension( lookInPanel.getPreferredButtonPanelSize().width - 5, lookInPanel.getPreferredButtonPanelSize().height));
185 		
186 		JPanel fieldPanel = new JPanel( new BorderLayout( 5, 0));
187 		fieldPanel.add( patternField, BorderLayout.CENTER);
188 		fieldPanel.add( filler, BorderLayout.EAST);
189 
190         patternErrorLabel = new JLabel(ERROR_ICON);
191         patternErrorLabel.setVisible(false);
192         patternErrorLabel.setBorder(new EmptyBorder(2, 0, 0, 0));
193         patternErrorLabel.setHorizontalAlignment(JLabel.LEFT);
194         
195         JPanel patternPanel = new JPanel(new FormLayout());
196         patternPanel.add(fieldPanel, FormLayout.FULL_FILL);
197         patternPanel.add(patternErrorLabel, FormLayout.FULL_FILL);
198 
199         JLabel patternLabel = new JLabel("Pattern:");
200         patternLabel.setPreferredSize(new Dimension(patternLabel.getPreferredSize().width, fieldPanel.getPreferredSize().height));
201         add( patternLabel, new FormConstraints( FormConstraints.LEFT, FormConstraints.RIGHT, FormConstraints.TOP));
202 		add( patternPanel, FormLayout.RIGHT_FILL);
203 		        
204 
205 		add( new JLabel(), FormLayout.LEFT);
206 		regexCheck = new JCheckBox( "Regular Expression");
207 
208         if (parent != null) {
209             parent.getProjectView().getFieldManager().addField( regexCheck);
210         }
211         
212 		add( regexCheck, FormLayout.RIGHT);
213         regexCheck.addItemListener(new UndoableCheckBoxItemListener(parent, regexCheck));
214         regexCheck.addItemListener(new ItemListener() {
215             public void itemStateChanged(ItemEvent arg0) {
216                 checkPattern();
217             }
218         });
219 
220         nodes = new ArrayList<OverviewNode>();
221         lookInNode = new DirectoryNode( parent, lookInField);
222         nodes.add(lookInNode);
223         nodes.add( new CheckBoxNode( parent, subdirCheck));
224         patternNode = new PatternNode( parent, patternField, regexCheck);
225         nodes.add(patternNode);
226 
227         if (resultEnabled) {
228             add(Box.createVerticalStrut(10), FormLayout.FULL);
229             add(new JSeparator(), FormLayout.FULL_FILL);
230             add(Box.createVerticalStrut(10), FormLayout.FULL);
231 
232             storeInField = new HistoryComboBox(parent, new HistoryComboBoxModel(HistoryUtilities.getInstance().getDirectories()));
233             storeInField.setPreferredSize(new Dimension(storeInField.getPreferredSize().width, dummyBrowseButton.getPreferredSize().height));
234             ((JTextField)storeInField.getEditor().getEditorComponent()).getDocument().addDocumentListener(new DocumentListener() {
235                 public void insertUpdate(DocumentEvent arg0) {
236                     checkField(storeInErrorLabel, storeInNode, storeInField);
237                 }
238 
239                 public void removeUpdate(DocumentEvent arg0) {
240                     checkField(storeInErrorLabel, storeInNode, storeInField);
241                 }
242 
243                 public void changedUpdate(DocumentEvent arg0) {}
244             });
245             
246             if (parent != null) {
247                 parent.getProjectView().getFieldManager().addField(storeInField);
248             }
249     
250             DirectorySelectionPanel storeInPanel = new DirectorySelectionPanel(storeInField);
251 
252             storeInErrorLabel = new JLabel(ERROR_ICON);
253             storeInErrorLabel.setVisible(false);
254             storeInErrorLabel.setBorder(new EmptyBorder(2, 0, 0, 0));
255             storeInErrorLabel.setHorizontalAlignment(JLabel.LEFT);
256             
257             JPanel storeInErrorPanel = new JPanel(new FormLayout());
258             storeInErrorPanel.add(storeInPanel, FormLayout.FULL_FILL);
259             storeInErrorPanel.add(storeInErrorLabel, FormLayout.FULL_FILL);
260 
261             JLabel storeInLabel = new JLabel("Store in:");
262             storeInLabel.setPreferredSize(new Dimension(storeInLabel.getPreferredSize().width, storeInPanel.getPreferredSize().height));
263             add(storeInLabel, new FormConstraints(FormConstraints.LEFT, FormConstraints.RIGHT, FormConstraints.TOP));
264             add(storeInErrorPanel, FormLayout.RIGHT_FILL);
265 
266             storeInNode = new DirectoryNode( parent, storeInField);
267             nodes.add(storeInNode);
268 
269             extensionField = new HistoryComboBox(parent, new HistoryComboBoxModel(HistoryUtilities.getInstance().getExtensions()));
270             extensionField.setFont(extensionField.getFont().deriveFont( Font.PLAIN));
271             extensionField.setPreferredSize(new Dimension(extensionField.getPreferredSize().width, dummyBrowseButton.getPreferredSize().height));
272 
273             if (parent != null) {
274                 parent.getProjectView().getFieldManager().addField(extensionField);
275             }
276 
277             filler = new JLabel();
278             filler.setPreferredSize(new Dimension( lookInPanel.getPreferredButtonPanelSize().width - 5, lookInPanel.getPreferredButtonPanelSize().height));
279             
280             fieldPanel = new JPanel( new BorderLayout( 5, 0));
281             fieldPanel.add(extensionField, BorderLayout.CENTER);
282             fieldPanel.add(filler, BorderLayout.EAST);
283 
284             add(new JLabel("Extension:"), new FormConstraints( FormConstraints.LEFT, FormConstraints.RIGHT));
285             add(fieldPanel, FormLayout.RIGHT_FILL);
286 
287 //            add(new JLabel(), FormLayout.LEFT);
288 //            flattenCheck = new JCheckBox("Flatten Structure");
289 //            parent.getProjectView().getFieldManager().addField(flattenCheck);
290 //            add(flattenCheck, FormLayout.RIGHT);
291 //            flattenCheck.addItemListener(new UndoableCheckBoxItemListener(parent, flattenCheck));
292 //
293 //            nodes.add(new CheckBoxNode(parent, flattenCheck));
294         }
295    	}
296 
297 	public void setFilter(URI base, Filter filter) {
298 		if ( filter != null) {
299 			lookInField.setValue( URIUtils.composePath(base, filter.getDir()));
300 
301             patternField.setValue( filter.getPattern());
302 			regexCheck.setSelected( filter.isRegex());
303 			subdirCheck.setSelected( filter.isIncludeSubdirectories());
304             if (storeInField != null) {
305                 storeInField.setValue(URIUtils.composePath(base, filter.getOutDir()));
306                 extensionField.setValue(filter.getExtension());
307             }
308 		} else {
309 			gotoHome(lookInField);
310 
311             if (storeInField != null) {
312                 gotoHome(storeInField);
313                 extensionField.setValue(null);
314             }
315 			
316             patternField.setValue( null);
317 			regexCheck.setSelected( false);
318 			subdirCheck.setSelected( false);
319 		}
320 	}
321 	
322     private void gotoHome(HistoryComboBox directoryField) {
323         directoryField.setValue((new File(System.getProperty("user.home"))).getAbsolutePath());
324     }
325 
326 	public Filter getFilter(URI base) {
327 		Filter filter = new Filter();
328 
329         filter.setDir(URIUtils.getRelativePath(base, new File(lookInField.getValue())));
330 		filter.setPattern(patternField.getValue());
331 		filter.setRegex(regexCheck.isSelected());
332 		filter.setIncludeSubdirectories(subdirCheck.isSelected());
333 
334         if (storeInField != null) {
335             filter.setExtension(extensionField.getValue());
336             filter.setOutDir(URIUtils.getRelativePath(base, new File(storeInField.getValue())));
337         }
338 
339 		return filter;
340 	}
341 	
342     public ArrayList<OverviewNode> getNodes() {
343         return nodes;
344     }
345     
346     public boolean isError() {
347         return false;
348     }
349 
350     private class PatternNode implements OverviewNode, ItemListener, DocumentListener {
351         private ArrayList<OverviewNode> empty = new ArrayList<OverviewNode>();
352         private JComboBox pattern = null;
353         private JCheckBox check = null;
354         private OverviewNode parent = null;
355         private String error = null;
356 
357         public PatternNode( OverviewNode parent, JComboBox pattern, JCheckBox check) {
358             this.parent = parent;
359             this.check = check;
360             this.pattern = pattern;
361             
362 			Component editor = pattern.getEditor().getEditorComponent();
363 			((JTextField)editor).getDocument().addDocumentListener(this);
364 			
365 			check.addItemListener( this);
366         }
367         
368         public String getNodeName() {
369             if ( check.isSelected()) {
370                 return (String)pattern.getEditor().getItem() + " (reg exp)";
371             }
372 
373             return (String)pattern.getEditor().getItem() + " (wildcard)";
374         }
375 
376         public ArrayList<OverviewNode> getChildNodes() {
377             return empty;
378         }
379 
380         public OverviewNode getParentNode() {
381             return parent;
382         }
383 
384         public Icon getNodeIcon() {
385        		return TEXT_FIELD_ICON;
386         }
387         
388 		public void itemStateChanged( ItemEvent e) {
389 			nodeChanged();
390 		}
391 
392 		public void nodeChanged() {
393         	OverviewNode node = parent;
394         	
395         	while ( node != null && !(node.getParentNode() instanceof OverviewTreeModel)) {
396         		node = node.getParentNode();
397         	}
398         	
399         	if ( node != null) {
400         		((OverviewTreeModel)node.getParentNode()).nodePathChanged( this);
401         	}
402         }
403 
404         public void insertUpdate(DocumentEvent arg0) {
405             nodeChanged();
406         }
407 
408         public void removeUpdate(DocumentEvent arg0) {
409             nodeChanged();
410         }
411 
412         public void changedUpdate(DocumentEvent arg0) {}
413 
414         public void setError(String error) {
415             this.error = error;
416         }
417 
418         public String getError() {
419             return error;
420         }
421     }
422     
423     private class DirectoryNode implements OverviewNode, ItemListener, DocumentListener {
424         private OverviewNode parent   = null;
425         private JComboBox dirField  = null;
426         private String error = null;
427         
428         public DirectoryNode( OverviewNode parent, JComboBox dirField)  {
429             this.dirField = dirField;
430             this.parent = parent;
431             
432             ((JTextField)dirField.getEditor().getEditorComponent()).getDocument().addDocumentListener( this);
433         }
434         
435         public String getNodeName() {
436             return dirField.getEditor().getItem() + " (dir)";
437         }
438     
439         public ArrayList<OverviewNode> getChildNodes() {
440             return new ArrayList<OverviewNode>();
441         }
442     
443         public OverviewNode getParentNode() {
444             return parent;
445         }
446     
447         public Icon getNodeIcon() {
448             return TEXT_FIELD_ICON;
449         }
450         
451         public void itemStateChanged( ItemEvent e) {
452             nodeChanged();
453         }
454     
455         public void nodeChanged() {
456             OverviewNode node = parent;
457             
458             while ( node != null && !(node.getParentNode() instanceof OverviewTreeModel)) {
459                 node = node.getParentNode();
460             }
461             
462             if ( node != null) {
463                 ((OverviewTreeModel)node.getParentNode()).nodePathChanged(this);
464             }
465         }
466     
467         public void setError(String error) {
468             this.error = error;
469         }
470 
471         public String getError() {
472             return error;
473         }
474 
475         public void insertUpdate(DocumentEvent arg0) {
476             nodeChanged();
477         }
478 
479         public void removeUpdate(DocumentEvent arg0) {
480             nodeChanged();
481         }
482 
483         public void changedUpdate(DocumentEvent arg0) {}
484     }
485     
486     private class DirectorySelectionPanel extends JPanel {
487         private static final long serialVersionUID = 1896718080795277304L;
488         
489         private JPanel buttonPanel              = null;
490         private HistoryComboBox directoryField  = null;
491         private JButton browseButton            = null;
492         private JButton homeButton              = null;
493         private JButton upButton                = null;
494 
495         public DirectorySelectionPanel(HistoryComboBox combo) {
496             super(new BorderLayout(0, 0));
497             
498             this.directoryField = combo;
499             
500             browseButton = new BrowseButton();
501             homeButton = new BrowseButton(HOME_ICON);
502             upButton = new BrowseButton(UP_ICON);
503 
504             JPanel uphomePanel = new JPanel( new FlowLayout( FlowLayout.LEFT, 5, 0));
505             uphomePanel.add(upButton);
506             uphomePanel.add(homeButton);
507 
508             buttonPanel = new JPanel( new BorderLayout( 11, 0));
509             buttonPanel.add(uphomePanel, BorderLayout.CENTER);
510             buttonPanel.add(browseButton, BorderLayout.EAST);
511             
512             add(directoryField, BorderLayout.CENTER);
513             add(buttonPanel, BorderLayout.EAST);
514                     
515             homeButton.addActionListener( new ActionListener() {
516                 public void actionPerformed( ActionEvent e) {
517                     gotoHome(directoryField);
518                 }
519             });
520 
521             upButton.addActionListener( new ActionListener() {
522                 public void actionPerformed( ActionEvent e) {
523                     upDirectory();
524                 }
525             });
526 
527             browseButton.addActionListener( new ActionListener() {
528                 public void actionPerformed( ActionEvent e) {
529                     chooseFile();
530                 }
531             });
532         }
533         
534         public Dimension getPreferredButtonPanelSize() {
535             return buttonPanel.getPreferredSize();
536         }
537         
538         private void chooseFile() {
539             String dir = directoryField.getValue();
540             if ( dir != null && dir.length() > 0) {
541                 chooser.setCurrentDirectory(new File(dir));
542             } else if ( ((HistoryComboBoxModel)directoryField.getModel()).getSize() > 0) {
543                 chooser.setSelectedFile(new File(((HistoryComboBoxModel)directoryField.getModel()).getElementAt(0).toString()));
544             }
545 
546             int value = chooser.showOpenDialog( this);
547 
548             if ( value == JFileChooser.APPROVE_OPTION) {
549                 directoryField.setValue( chooser.getSelectedFile().getAbsolutePath());
550             }
551         }
552 
553         private void upDirectory() {
554             File file = new File(directoryField.getValue());
555 
556             if ( file != null) {
557                 file = file.getParentFile();
558                 
559                 if (file != null) {
560                     directoryField.setValue( file.getAbsolutePath());
561                 }
562             }
563         }
564     }
565     
566     private void checkPattern() {
567         if (regexCheck.isSelected()) {
568             try {
569                 Pattern.compile(patternField.getValue());
570                 patternNode.setError(null);
571                 patternErrorLabel.setVisible(false);
572             } catch (Throwable cause) {
573                 while (cause.getCause() != null) {
574                     cause = cause.getCause();
575                 }
576         
577                 patternNode.setError(cause.getMessage());
578                 patternErrorLabel.setText(cause.getMessage());
579                 patternErrorLabel.setVisible(true);
580             }
581         } else {
582             patternNode.setError(null);
583             patternErrorLabel.setVisible(false);
584         }
585     }
586     
587     private void checkField(JLabel errorLabel, DirectoryNode node, HistoryComboBox field) {
588         try {
589             File file = new File(field.getValue());
590             
591             if (!file.exists()) {
592                 errorLabel.setText("Path should exist");
593                 node.setError("Path should exist");
594                 errorLabel.setVisible(true);
595             } else if (!file.isAbsolute()) {
596                 node.setError("Absolute path expected");
597                 errorLabel.setText("Absolute path expected");
598                 errorLabel.setVisible(true);
599             } else if (!file.isDirectory()) {
600                 node.setError("Path should indicate a directory");
601                 errorLabel.setText("Path should indicate a directory");
602                 errorLabel.setVisible(true);
603             } else {
604                 node.setError(null);
605                 errorLabel.setVisible(false);
606             }
607         } catch (Throwable cause) {
608             while (cause.getCause() != null) {
609                 cause = cause.getCause();
610             }
611     
612             node.setError(cause.getMessage());
613             errorLabel.setText(cause.getMessage());
614             errorLabel.setVisible(true);
615         }
616     }
617 }