Lines 68-73
Link Here
|
68 |
import java.beans.PropertyChangeEvent; |
68 |
import java.beans.PropertyChangeEvent; |
69 |
import java.beans.PropertyChangeListener; |
69 |
import java.beans.PropertyChangeListener; |
70 |
import java.io.File; |
70 |
import java.io.File; |
|
|
71 |
import java.io.FileNotFoundException; |
71 |
import java.io.IOException; |
72 |
import java.io.IOException; |
72 |
import java.lang.ref.WeakReference; |
73 |
import java.lang.ref.WeakReference; |
73 |
import java.lang.reflect.Constructor; |
74 |
import java.lang.reflect.Constructor; |
Lines 95-100
Link Here
|
95 |
import java.util.logging.Logger; |
96 |
import java.util.logging.Logger; |
96 |
import java.util.regex.Matcher; |
97 |
import java.util.regex.Matcher; |
97 |
import java.util.regex.Pattern; |
98 |
import java.util.regex.Pattern; |
|
|
99 |
import java.util.regex.PatternSyntaxException; |
98 |
import javax.swing.AbstractAction; |
100 |
import javax.swing.AbstractAction; |
99 |
import javax.swing.AbstractListModel; |
101 |
import javax.swing.AbstractListModel; |
100 |
import javax.swing.Action; |
102 |
import javax.swing.Action; |
Lines 136-142
Link Here
|
136 |
import javax.swing.filechooser.FileSystemView; |
138 |
import javax.swing.filechooser.FileSystemView; |
137 |
import javax.swing.filechooser.FileView; |
139 |
import javax.swing.filechooser.FileView; |
138 |
import javax.swing.plaf.ActionMapUIResource; |
140 |
import javax.swing.plaf.ActionMapUIResource; |
139 |
import javax.swing.plaf.ComponentUI; |
|
|
140 |
import javax.swing.plaf.UIResource; |
141 |
import javax.swing.plaf.UIResource; |
141 |
import javax.swing.plaf.basic.BasicFileChooserUI; |
142 |
import javax.swing.plaf.basic.BasicFileChooserUI; |
142 |
import javax.swing.tree.DefaultMutableTreeNode; |
143 |
import javax.swing.tree.DefaultMutableTreeNode; |
Lines 157-169
Link Here
|
157 |
import org.openide.util.NbPreferences; |
158 |
import org.openide.util.NbPreferences; |
158 |
import org.openide.util.RequestProcessor; |
159 |
import org.openide.util.RequestProcessor; |
159 |
import org.openide.util.Utilities; |
160 |
import org.openide.util.Utilities; |
|
|
161 |
import sun.awt.shell.ShellFolder; |
162 |
import sun.swing.FilePane; |
160 |
|
163 |
|
161 |
/** |
164 |
/** |
162 |
* An implementation of a customized filechooser. |
165 |
* An implementation of a customized filechooser. |
163 |
* |
166 |
* |
164 |
* @author Soot Phengsy, inspired by Jeff Dinkins' Swing version |
167 |
* @author Soot Phengsy, inspired by Jeff Dinkins' Swing version |
165 |
*/ |
168 |
*/ |
166 |
class FileChooserUIImpl extends BasicFileChooserUI{ |
169 |
final class FileChooserUIImpl extends BasicFileChooserUI{ |
167 |
|
170 |
|
168 |
static final String USE_SHELL_FOLDER = "FileChooser.useShellFolder";//NOI18N |
171 |
static final String USE_SHELL_FOLDER = "FileChooser.useShellFolder";//NOI18N |
169 |
static final String NB_USE_SHELL_FOLDER = "nb.FileChooser.useShellFolder";//NOI18N |
172 |
static final String NB_USE_SHELL_FOLDER = "nb.FileChooser.useShellFolder";//NOI18N |
Lines 184-189
Link Here
|
184 |
|
187 |
|
185 |
private static final RequestProcessor COMMON_RP = new RequestProcessor("Cnd File Chooser Common Worker", 16); // NOI18N |
188 |
private static final RequestProcessor COMMON_RP = new RequestProcessor("Cnd File Chooser Common Worker", 16); // NOI18N |
186 |
private static final RequestProcessor UPDATE_RP = new RequestProcessor("Cnd File Chooser Update Worker"); // NOI18N |
189 |
private static final RequestProcessor UPDATE_RP = new RequestProcessor("Cnd File Chooser Update Worker"); // NOI18N |
|
|
190 |
private static final RequestProcessor APPROVE_RP = new RequestProcessor("Cnd File Chooser Update Worker"); // NOI18N |
187 |
|
191 |
|
188 |
private static final String TIMEOUT_KEY="nb.fileChooser.timeout"; // NOI18N |
192 |
private static final String TIMEOUT_KEY="nb.fileChooser.timeout"; // NOI18N |
189 |
|
193 |
|
Lines 276-292
Link Here
|
276 |
private final RequestProcessor.Task listFilesTask = UPDATE_RP.create(listFilesWorker); |
280 |
private final RequestProcessor.Task listFilesTask = UPDATE_RP.create(listFilesWorker); |
277 |
private volatile File curDir; |
281 |
private volatile File curDir; |
278 |
|
282 |
|
279 |
public static ComponentUI createUI(JComponent c) { |
283 |
private final Action approveSelectionAction; |
280 |
return new FileChooserUIImpl((JFileChooserEx) c); |
284 |
private final Action cancelSelectionAction; |
281 |
} |
285 |
private final AtomicBoolean cancelled = new AtomicBoolean(false); |
|
|
286 |
|
287 |
private FileFilter actualFileFilter = null; |
288 |
private GlobFilter globFilter = null; |
282 |
|
289 |
|
283 |
public FileChooserUIImpl(FileChooserBuilder.JFileChooserEx filechooser) { |
290 |
public FileChooserUIImpl(FileChooserBuilder.JFileChooserEx filechooser) { |
284 |
super(filechooser); |
291 |
super(filechooser); |
|
|
292 |
approveSelectionAction = new ApproveSelectionAction(); |
293 |
cancelSelectionAction = new CancelSelectionAction(); |
285 |
} |
294 |
} |
286 |
|
295 |
|
287 |
@Override |
296 |
@Override |
288 |
public void installUI(JComponent c) { |
297 |
public void installUI(JComponent c) { |
289 |
super.installUI(c); |
298 |
super.installUI(c); |
|
|
299 |
fileChooser = (JFileChooserEx) c; |
290 |
} |
300 |
} |
291 |
|
301 |
|
292 |
@Override |
302 |
@Override |
Lines 1409-1415
Link Here
|
1409 |
AbstractAction escAction = new AbstractAction() { |
1419 |
AbstractAction escAction = new AbstractAction() { |
1410 |
@Override |
1420 |
@Override |
1411 |
public void actionPerformed(ActionEvent e) { |
1421 |
public void actionPerformed(ActionEvent e) { |
1412 |
getFileChooser().cancelSelection(); |
1422 |
getCancelSelectionAction().actionPerformed(e); |
1413 |
} |
1423 |
} |
1414 |
@Override |
1424 |
@Override |
1415 |
public boolean isEnabled(){ |
1425 |
public boolean isEnabled(){ |
Lines 3109-3113
Link Here
|
3109 |
} |
3119 |
} |
3110 |
|
3120 |
|
3111 |
} // end of UpdateWorker |
3121 |
} // end of UpdateWorker |
|
|
3122 |
|
3123 |
@Override |
3124 |
public Action getApproveSelectionAction() { |
3125 |
return approveSelectionAction; |
3126 |
} |
3127 |
|
3128 |
@Override |
3129 |
public Action getCancelSelectionAction() { |
3130 |
return cancelSelectionAction; |
3131 |
} |
3132 |
|
3133 |
private class CancelSelectionAction extends AbstractAction { |
3134 |
public void actionPerformed(ActionEvent e) { |
3135 |
cancelled.set(true); |
3136 |
getFileChooser().cancelSelection(); |
3137 |
} |
3138 |
} |
3139 |
|
3140 |
private class ApproveSelectionAction extends AbstractAction { |
3141 |
|
3142 |
protected ApproveSelectionAction() { |
3143 |
super(FilePane.ACTION_APPROVE_SELECTION); |
3144 |
} |
3145 |
|
3146 |
@Override |
3147 |
public void actionPerformed(final ActionEvent e) { |
3148 |
if (isDirectorySelected()) { |
3149 |
File dir = getDirectory(); |
3150 |
if (dir != null) { |
3151 |
try { |
3152 |
// Strip trailing ".." |
3153 |
dir = ShellFolder.getNormalizedFile(dir); |
3154 |
} catch (IOException ex) { |
3155 |
// Ok, use f as is |
3156 |
} |
3157 |
changeDirectory(dir); |
3158 |
return; |
3159 |
} |
3160 |
} |
3161 |
|
3162 |
String filename = getFileName(); |
3163 |
|
3164 |
if (filename != null) { |
3165 |
// VK: why isn't it just trim() ? - do we really need leading spaces?? |
3166 |
// Remove whitespaces from end of filename |
3167 |
int i = filename.length() - 1; |
3168 |
while (i >=0 && filename.charAt(i) <= ' ') { |
3169 |
i--; |
3170 |
} |
3171 |
filename = filename.substring(0, i + 1); |
3172 |
} |
3173 |
|
3174 |
if (filename == null || filename.length() == 0) { |
3175 |
// no file selected, multiple selection off, therefore cancel the approve action |
3176 |
resetGlobFilter(); |
3177 |
return; |
3178 |
} |
3179 |
|
3180 |
// Unix: Resolve '~' to user's home directory |
3181 |
if (fileChooser.isUnix()) { |
3182 |
if (filename.startsWith("~/")) { |
3183 |
filename = fileChooser.getHomePath() + filename.substring(1); |
3184 |
} else if (filename.equals("~")) { |
3185 |
filename = fileChooser.getHomePath(); |
3186 |
} |
3187 |
} |
3188 |
|
3189 |
// in the case of single selectiom, use selectedFiles.get(0) |
3190 |
final List<File> selectedFiles = new ArrayList<>(); |
3191 |
|
3192 |
enableAllButCancel(false); |
3193 |
ApproveSelectionFinisher finisher = new ApproveSelectionFinisher(e, filename, selectedFiles, cancelled); |
3194 |
ApproveSelectionThreadWorker worker = new ApproveSelectionThreadWorker( |
3195 |
e, filename, fileChooser.isMultiSelectionEnabled(), |
3196 |
fileChooser.getCurrentDirectory(), fileChooser.getFileSystemView(), |
3197 |
selectedFiles, finisher); |
3198 |
APPROVE_RP.post(worker); |
3199 |
} |
3200 |
|
3201 |
private void cancel() { |
3202 |
cancelled.set(true); |
3203 |
} |
3204 |
} |
3205 |
|
3206 |
private static class ApproveSelectionThreadWorker implements Runnable { |
3207 |
|
3208 |
private final ActionEvent e; |
3209 |
private final String filename; |
3210 |
private final boolean multySelection; |
3211 |
private final File currentDir; |
3212 |
private final FileSystemView fs; |
3213 |
private final List<File> selectedFiles; |
3214 |
private final ApproveSelectionFinisher finisher; |
3215 |
|
3216 |
public ApproveSelectionThreadWorker(ActionEvent e, String filename, boolean multySelection, File currentDir, FileSystemView fs, List<File> selectedFiles, ApproveSelectionFinisher finisher) { |
3217 |
this.e = e; |
3218 |
this.filename = filename; |
3219 |
this.multySelection = multySelection; |
3220 |
this.currentDir = currentDir; |
3221 |
this.fs = fs; |
3222 |
this.selectedFiles = selectedFiles; |
3223 |
this.finisher = finisher; |
3224 |
} |
3225 |
|
3226 |
@Override |
3227 |
public void run() { |
3228 |
try { |
3229 |
if (multySelection && filename.length() > 1 && |
3230 |
filename.charAt(0) == '"' && filename.charAt(filename.length() - 1) == '"') { |
3231 |
|
3232 |
// VK: double space between \" breaks this?! |
3233 |
String[] files = filename.substring(1, filename.length() - 1).split("\" \""); |
3234 |
// Optimize searching files by names in "children" array |
3235 |
Arrays.sort(files); |
3236 |
|
3237 |
File[] children = null; |
3238 |
int childIndex = 0; |
3239 |
|
3240 |
for (String str : files) { |
3241 |
File file = fs.createFileObject(str); |
3242 |
if (!file.isAbsolute()) { |
3243 |
if (children == null) { |
3244 |
children = fs.getFiles(currentDir, false); |
3245 |
Arrays.sort(children); |
3246 |
} |
3247 |
for (int k = 0; k < children.length; k++) { |
3248 |
int l = (childIndex + k) % children.length; |
3249 |
if (children[l].getName().equals(str)) { |
3250 |
file = children[l]; |
3251 |
childIndex = l + 1; |
3252 |
break; |
3253 |
} |
3254 |
} |
3255 |
} |
3256 |
selectedFiles.add(file); |
3257 |
} |
3258 |
} else { |
3259 |
File selectedFile = fs.createFileObject(filename); |
3260 |
if (!selectedFile.isAbsolute()) { |
3261 |
selectedFile = fs.getChild(currentDir, filename); |
3262 |
} |
3263 |
selectedFiles.add(selectedFile); |
3264 |
} |
3265 |
} finally { |
3266 |
SwingUtilities.invokeLater(finisher); |
3267 |
} |
3268 |
} |
3269 |
} |
3270 |
|
3271 |
private class ApproveSelectionFinisher implements Runnable { |
3272 |
|
3273 |
private final String filename; |
3274 |
private final List<File> selectedFiles; |
3275 |
private final ActionEvent e; |
3276 |
private final AtomicBoolean cancelled; |
3277 |
|
3278 |
public ApproveSelectionFinisher(ActionEvent e, String filename, List<File> selectedFiles, AtomicBoolean cancelled) { |
3279 |
this.e = e; |
3280 |
this.selectedFiles = selectedFiles; |
3281 |
this.filename = filename; |
3282 |
this.cancelled = cancelled; |
3283 |
} |
3284 |
|
3285 |
@Override |
3286 |
public void run() { |
3287 |
|
3288 |
if (cancelled.get()) { |
3289 |
return; |
3290 |
} |
3291 |
|
3292 |
enableAllButCancel(true); |
3293 |
|
3294 |
JFileChooser chooser = getFileChooser(); |
3295 |
resetGlobFilter(); |
3296 |
|
3297 |
if (selectedFiles.size() == 1) { |
3298 |
|
3299 |
File selectedFile = selectedFiles.get(0); |
3300 |
|
3301 |
// check for wildcard pattern |
3302 |
FileFilter currentFilter = chooser.getFileFilter(); |
3303 |
if (!selectedFile.exists() && isGlobPattern(filename)) { |
3304 |
changeDirectory(selectedFile.getParentFile()); |
3305 |
if (globFilter == null) { |
3306 |
globFilter = new GlobFilter(); |
3307 |
} |
3308 |
try { |
3309 |
globFilter.setPattern(selectedFile.getName()); |
3310 |
if (!(currentFilter instanceof GlobFilter)) { |
3311 |
actualFileFilter = currentFilter; |
3312 |
} |
3313 |
chooser.setFileFilter(null); |
3314 |
chooser.setFileFilter(globFilter); |
3315 |
return; |
3316 |
} catch (PatternSyntaxException pse) { |
3317 |
// Not a valid glob pattern. Abandon filter. |
3318 |
} |
3319 |
} |
3320 |
|
3321 |
// Check for directory change action |
3322 |
boolean isDir = (selectedFile != null && selectedFile.isDirectory()); |
3323 |
boolean isTrav = (selectedFile != null && chooser.isTraversable(selectedFile)); |
3324 |
boolean isDirSelEnabled = chooser.isDirectorySelectionEnabled(); |
3325 |
boolean isFileSelEnabled = chooser.isFileSelectionEnabled(); |
3326 |
boolean isCtrl = (e != null && (e.getModifiers() & |
3327 |
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0); |
3328 |
|
3329 |
if (isDir && isTrav && (isCtrl || !isDirSelEnabled)) { |
3330 |
changeDirectory(selectedFile); |
3331 |
return; |
3332 |
} else if ((isDir || !isFileSelEnabled) |
3333 |
&& (!isDir || !isDirSelEnabled) |
3334 |
&& (!isDirSelEnabled || selectedFile.exists())) { |
3335 |
selectedFiles.clear(); |
3336 |
} |
3337 |
} |
3338 |
|
3339 |
|
3340 |
if (!selectedFiles.isEmpty()) { |
3341 |
if (chooser.isMultiSelectionEnabled()) { |
3342 |
final File[] selectedFilesArray = selectedFiles.toArray(new File[selectedFiles.size()]); |
3343 |
chooser.setSelectedFiles(selectedFilesArray); |
3344 |
// Do it again. This is a fix for bug 4949273 to force the |
3345 |
// selected value in case the ListSelectionModel clears it |
3346 |
// for non-existing file names. |
3347 |
chooser.setSelectedFiles(selectedFilesArray); |
3348 |
} else { |
3349 |
chooser.setSelectedFile(selectedFiles.get(0)); |
3350 |
} |
3351 |
chooser.approveSelection(); |
3352 |
} else { |
3353 |
if (chooser.isMultiSelectionEnabled()) { |
3354 |
chooser.setSelectedFiles(null); |
3355 |
} else { |
3356 |
chooser.setSelectedFile(null); |
3357 |
} |
3358 |
chooser.cancelSelection(); |
3359 |
} |
3360 |
} |
3361 |
} |
3362 |
|
3363 |
private void enableAllButCancel(boolean enable) { |
3364 |
FileChooserUIImpl.this.newFolderButton.setEnabled(enable); |
3365 |
FileChooserUIImpl.this.approveButton.setEnabled(enable); |
3366 |
// FileChooserUIImpl.this.topCombo.setEnabled(enable); |
3367 |
// FileChooserUIImpl.this.filenameTextField.setEditable(enable); |
3368 |
// FileChooserUIImpl.this.filenameTextField.setEnabled(enable); |
3369 |
// FileChooserUIImpl.this.filterTypeComboBox.setEnabled(enable); |
3370 |
// FileChooserUIImpl.this.tree.setEnabled(enable); |
3371 |
} |
3372 |
|
3373 |
private void changeDirectory(File dir) { |
3374 |
JFileChooser fc = getFileChooser(); |
3375 |
// Traverse shortcuts on Windows |
3376 |
if (dir != null && FilePane.usesShellFolder(fc)) { |
3377 |
try { |
3378 |
ShellFolder shellFolder = ShellFolder.getShellFolder(dir); |
3379 |
|
3380 |
if (shellFolder.isLink()) { |
3381 |
File linkedTo = shellFolder.getLinkLocation(); |
3382 |
|
3383 |
// If linkedTo is null we try to use dir |
3384 |
if (linkedTo != null) { |
3385 |
if (fc.isTraversable(linkedTo)) { |
3386 |
dir = linkedTo; |
3387 |
} else { |
3388 |
return; |
3389 |
} |
3390 |
} else { |
3391 |
dir = shellFolder; |
3392 |
} |
3393 |
} |
3394 |
} catch (FileNotFoundException ex) { |
3395 |
return; |
3396 |
} |
3397 |
} |
3398 |
fc.setCurrentDirectory(dir); |
3399 |
if (fc.getFileSelectionMode() == JFileChooser.FILES_AND_DIRECTORIES && |
3400 |
fc.getFileSystemView().isFileSystem(dir)) { |
3401 |
|
3402 |
setFileName(dir.getAbsolutePath()); |
3403 |
} |
3404 |
} |
3405 |
|
3406 |
private void resetGlobFilter() { |
3407 |
if (actualFileFilter != null) { |
3408 |
JFileChooser chooser = getFileChooser(); |
3409 |
FileFilter currentFilter = chooser.getFileFilter(); |
3410 |
if (currentFilter != null && currentFilter.equals(globFilter)) { |
3411 |
chooser.setFileFilter(actualFileFilter); |
3412 |
chooser.removeChoosableFileFilter(globFilter); |
3413 |
} |
3414 |
actualFileFilter = null; |
3415 |
} |
3416 |
} |
3417 |
|
3418 |
private static boolean isGlobPattern(String filename) { |
3419 |
return ((File.separatorChar == '\\' && (filename.indexOf('*') >= 0 |
3420 |
|| filename.indexOf('?') >= 0)) |
3421 |
|| (File.separatorChar == '/' && (filename.indexOf('*') >= 0 |
3422 |
|| filename.indexOf('?') >= 0 |
3423 |
|| filename.indexOf('[') >= 0))); |
3424 |
} |
3425 |
|
3426 |
|
3427 |
/* A file filter which accepts file patterns containing |
3428 |
* the special wildcards *? on Windows and *?[] on Unix. |
3429 |
*/ |
3430 |
class GlobFilter extends FileFilter { |
3431 |
Pattern pattern; |
3432 |
String globPattern; |
3433 |
|
3434 |
public void setPattern(String globPattern) { |
3435 |
char[] gPat = globPattern.toCharArray(); |
3436 |
char[] rPat = new char[gPat.length * 2]; |
3437 |
boolean isWin32 = (File.separatorChar == '\\'); |
3438 |
boolean inBrackets = false; |
3439 |
int j = 0; |
3440 |
|
3441 |
this.globPattern = globPattern; |
3442 |
|
3443 |
if (isWin32) { |
3444 |
// On windows, a pattern ending with *.* is equal to ending with * |
3445 |
int len = gPat.length; |
3446 |
if (globPattern.endsWith("*.*")) { |
3447 |
len -= 2; |
3448 |
} |
3449 |
for (int i = 0; i < len; i++) { |
3450 |
switch(gPat[i]) { |
3451 |
case '*': |
3452 |
rPat[j++] = '.'; |
3453 |
rPat[j++] = '*'; |
3454 |
break; |
3455 |
|
3456 |
case '?': |
3457 |
rPat[j++] = '.'; |
3458 |
break; |
3459 |
|
3460 |
case '\\': |
3461 |
rPat[j++] = '\\'; |
3462 |
rPat[j++] = '\\'; |
3463 |
break; |
3464 |
|
3465 |
default: |
3466 |
if ("+()^$.{}[]".indexOf(gPat[i]) >= 0) { |
3467 |
rPat[j++] = '\\'; |
3468 |
} |
3469 |
rPat[j++] = gPat[i]; |
3470 |
break; |
3471 |
} |
3472 |
} |
3473 |
} else { |
3474 |
for (int i = 0; i < gPat.length; i++) { |
3475 |
switch(gPat[i]) { |
3476 |
case '*': |
3477 |
if (!inBrackets) { |
3478 |
rPat[j++] = '.'; |
3479 |
} |
3480 |
rPat[j++] = '*'; |
3481 |
break; |
3482 |
|
3483 |
case '?': |
3484 |
rPat[j++] = inBrackets ? '?' : '.'; |
3485 |
break; |
3486 |
|
3487 |
case '[': |
3488 |
inBrackets = true; |
3489 |
rPat[j++] = gPat[i]; |
3490 |
|
3491 |
if (i < gPat.length - 1) { |
3492 |
switch (gPat[i+1]) { |
3493 |
case '!': |
3494 |
case '^': |
3495 |
rPat[j++] = '^'; |
3496 |
i++; |
3497 |
break; |
3498 |
|
3499 |
case ']': |
3500 |
rPat[j++] = gPat[++i]; |
3501 |
break; |
3502 |
} |
3503 |
} |
3504 |
break; |
3505 |
|
3506 |
case ']': |
3507 |
rPat[j++] = gPat[i]; |
3508 |
inBrackets = false; |
3509 |
break; |
3510 |
|
3511 |
case '\\': |
3512 |
if (i == 0 && gPat.length > 1 && gPat[1] == '~') { |
3513 |
rPat[j++] = gPat[++i]; |
3514 |
} else { |
3515 |
rPat[j++] = '\\'; |
3516 |
if (i < gPat.length - 1 && "*?[]".indexOf(gPat[i+1]) >= 0) { |
3517 |
rPat[j++] = gPat[++i]; |
3518 |
} else { |
3519 |
rPat[j++] = '\\'; |
3520 |
} |
3521 |
} |
3522 |
break; |
3523 |
|
3524 |
default: |
3525 |
//if ("+()|^$.{}<>".indexOf(gPat[i]) >= 0) { |
3526 |
if (!Character.isLetterOrDigit(gPat[i])) { |
3527 |
rPat[j++] = '\\'; |
3528 |
} |
3529 |
rPat[j++] = gPat[i]; |
3530 |
break; |
3531 |
} |
3532 |
} |
3533 |
} |
3534 |
this.pattern = Pattern.compile(new String(rPat, 0, j), Pattern.CASE_INSENSITIVE); |
3535 |
} |
3536 |
|
3537 |
@Override |
3538 |
public boolean accept(File f) { |
3539 |
if (f == null) { |
3540 |
return false; |
3541 |
} |
3542 |
if (f.isDirectory()) { |
3543 |
return true; |
3544 |
} |
3545 |
return pattern.matcher(f.getName()).matches(); |
3546 |
} |
3547 |
|
3548 |
@Override |
3549 |
public String getDescription() { |
3550 |
return globPattern; |
3551 |
} |
3552 |
} |
3112 |
|
3553 |
|
3113 |
} |
3554 |
} |