KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > spi > java > project > support > ui > IncludeExcludeVisualizer


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.spi.java.project.support.ui;
21
22 import java.awt.EventQueue JavaDoc;
23 import java.io.File JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.SortedSet JavaDoc;
27 import java.util.TreeSet JavaDoc;
28 import java.util.regex.Pattern JavaDoc;
29 import javax.swing.JComponent JavaDoc;
30 import javax.swing.event.ChangeEvent JavaDoc;
31 import javax.swing.event.ChangeListener JavaDoc;
32 import org.netbeans.spi.project.support.ant.PathMatcher;
33 import org.openide.util.NbPreferences;
34 import org.openide.util.Parameters;
35 import org.openide.util.RequestProcessor;
36
37 /**
38  * Utility permitting a user to easily see the effect of changing include
39  * and exclude patterns on a source group (or several).
40  * Intended for use in project creation wizards and project properties dialogs.
41  * The exact appearance of the panel is not specified but it should
42  * permit the user to see, and edit, the current set of includes and excludes;
43  * and display the set of files included and excluded by the current pattern.
44  * @see PathMatcher
45  * @since org.netbeans.modules.java.project/1 1.12
46  * @author Jesse Glick
47  */

48 public class IncludeExcludeVisualizer {
49
50     private File JavaDoc[] roots = {};
51     private String JavaDoc includes = "**"; // NOI18N
52
private String JavaDoc excludes = ""; // NOI18N
53
private final List JavaDoc<ChangeListener JavaDoc> listeners = new ArrayList JavaDoc<ChangeListener JavaDoc>(1);
54     private IncludeExcludeVisualizerPanel panel;
55     private SortedSet JavaDoc<File JavaDoc> included = new TreeSet JavaDoc<File JavaDoc>();
56     private SortedSet JavaDoc<File JavaDoc> excluded = new TreeSet JavaDoc<File JavaDoc>();
57     private boolean busy = false;
58     private boolean interrupted = false;
59     private static final RequestProcessor RP = new RequestProcessor(IncludeExcludeVisualizer.class.getName());
60     private final RequestProcessor.Task task = RP.create(new RecalculateTask());
61
62     /**
63      * Create a new visualizer.
64      * Initially has no roots and includes anything (equivalent to
65      * an include pattern of <samp>**</samp> and an empty exclude pattern).
66      */

67     public IncludeExcludeVisualizer() {}
68
69     /**
70      * Configure a set of root directories to which the includes and excludes apply.
71      * @param roots a set of root directories to search
72      * @throws IllegalArgumentException if roots contains a non-directory
73      */

74     public synchronized void setRoots(File JavaDoc[] roots) throws IllegalArgumentException JavaDoc {
75         Parameters.notNull("roots", roots);
76         for (File JavaDoc root : roots) {
77             if (!root.isDirectory()) {
78                 throw new IllegalArgumentException JavaDoc(root.getAbsolutePath());
79             }
80         }
81         this.roots = roots;
82         recalculate();
83     }
84
85     /**
86      * Get the current include pattern.
87      * @return the current pattern (never null)
88      */

89     public synchronized String JavaDoc getIncludePattern() {
90         return includes;
91     }
92
93     /**
94      * Set the include pattern.
95      * This does not fire a change event.
96      * @param pattern the new pattern (never null)
97      */

98     public synchronized void setIncludePattern(String JavaDoc pattern) {
99         Parameters.notNull("pattern", pattern);
100         includes = pattern;
101         updateIncludesExcludes();
102         recalculate();
103     }
104
105     /**
106      * Get the current exclude pattern.
107      * @return the current pattern (never null)
108      */

109     public synchronized String JavaDoc getExcludePattern() {
110         return excludes;
111     }
112
113     /**
114      * Set the exclude pattern.
115      * This does not fire a change event.
116      * @param pattern the new pattern (never null)
117      */

118     public synchronized void setExcludePattern(String JavaDoc pattern) {
119         Parameters.notNull("pattern", pattern);
120         excludes = pattern;
121         updateIncludesExcludes();
122         recalculate();
123     }
124
125     private synchronized void updateIncludesExcludes() {
126         if (panel != null) {
127             EventQueue.invokeLater(new Runnable JavaDoc() {
128                 public void run() {
129                     panel.setFields(includes, excludes);
130                 }
131             });
132         }
133     }
134
135     /**
136      * Add a listener to changes made by the user in the includes or excludes.
137      * @param l the listener
138      */

139     public synchronized void addChangeListener(ChangeListener JavaDoc l) {
140         listeners.add(l);
141     }
142
143     /**
144      * Remove a change listener.
145      * @param l the listener
146      */

147     public synchronized void removeChangeListener(ChangeListener JavaDoc l) {
148         listeners.remove(l);
149     }
150
151     /**
152      * Can be called from IncludeExcludeVisualizerPanel.
153      */

154     synchronized void changedPatterns(String JavaDoc includes, String JavaDoc excludes) {
155         this.includes = includes;
156         this.excludes = excludes;
157         recalculate();
158         fireChange();
159     }
160
161     private synchronized void fireChange() {
162         ChangeEvent JavaDoc e = new ChangeEvent JavaDoc(this);
163         for (ChangeListener JavaDoc l : listeners) {
164             l.stateChanged(e);
165         }
166     }
167
168     /**
169      * Get the associated visual panel.
170      * @return a panel displaying this include and exclude information
171      * @throws IllegalThreadStateException if not called in the event thread
172      */

173     public synchronized JComponent JavaDoc getVisualizerPanel() {
174         if (!EventQueue.isDispatchThread()) {
175             throw new IllegalThreadStateException JavaDoc("must be called in EQ");
176         }
177         if (panel == null) {
178             panel = new IncludeExcludeVisualizerPanel(this);
179             panel.setFields(includes, excludes);
180             panel.setFiles(included.toArray(new File JavaDoc[included.size()]), excluded.toArray(new File JavaDoc[excluded.size()]), busy);
181         }
182         return panel;
183     }
184
185     private static final int DELAY = 200;
186     private synchronized void recalculate() {
187         interrupted = true;
188         task.schedule(DELAY);
189     }
190
191     private void updateFiles() {
192         assert Thread.holdsLock(this);
193         EventQueue.invokeLater(new Runnable JavaDoc() {
194             public void run() {
195                 synchronized (IncludeExcludeVisualizer.this) {
196                     if (panel != null) {
197                         panel.setFiles(included.toArray(new File JavaDoc[included.size()]), excluded.toArray(new File JavaDoc[excluded.size()]), busy);
198                     }
199                 }
200             }
201         });
202     }
203
204     private int scanCounter;
205     private static final int GRANULARITY = 1000;
206     private void scan(File JavaDoc d, String JavaDoc prefix, PathMatcher matcher, Pattern JavaDoc ignoredFiles) {
207         String JavaDoc[] children = d.list();
208         if (children == null) {
209             return;
210         }
211         for (String JavaDoc child : children) {
212             if (ignoredFiles.matcher(child).find()) {
213                 continue;
214             }
215             File JavaDoc f = new File JavaDoc(d, child);
216             boolean dir = f.isDirectory();
217             if (dir) {
218                 scan(f, prefix + child + "/", matcher, ignoredFiles); // NOI18N
219
} else {
220                 synchronized (this) {
221                     if (interrupted) {
222                         return;
223                     }
224                     if (matcher.matches(prefix + child, false)) {
225                         included.add(f);
226                     } else {
227                         excluded.add(f);
228                     }
229                     if (++scanCounter % GRANULARITY == 0) {
230                         updateFiles();
231                     }
232                 }
233             }
234         }
235     }
236
237     private final class RecalculateTask implements Runnable JavaDoc {
238
239         // XXX #95974: VisibilityQuery only works on FileObject, and that would be too slow
240
// copied from: org.netbeans.modules.masterfs.GlobalVisibilityQueryImpl
241
final Pattern JavaDoc ignoredFiles = Pattern.compile(NbPreferences.root().node("/org/netbeans/core"). // NOI18N
242
get("IgnoredFiles", "^(CVS|SCCS|vssver\\.scc|#.*#|%.*%|\\.(cvsignore|svn|DS_Store)|_svn)$|~$|^\\..*$")); // NOI18N
243

244         public void run() {
245             File JavaDoc[] _roots;
246             String JavaDoc _includes, _excludes;
247             synchronized (IncludeExcludeVisualizer.this) {
248                 busy = true;
249                 included.clear();
250                 excluded.clear();
251                 _roots = roots.clone();
252                 _includes = includes;
253                 _excludes = excludes;
254                 interrupted = false;
255                 updateFiles();
256             }
257             PathMatcher matcher = new PathMatcher(_includes, _excludes, null);
258             for (File JavaDoc root : _roots) {
259                 scan(root, "", matcher, ignoredFiles);
260             }
261             synchronized (IncludeExcludeVisualizer.this) {
262                 busy = false;
263                 updateFiles();
264             }
265         }
266
267     }
268
269 }
270
Popular Tags