/*
* Copyright (c) 2005-2016 Flamingo Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of Flamingo Kirill Grouchnikov nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.pushingpixels.flamingo.api.bcb.core;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import javax.swing.filechooser.FileSystemView;
import org.pushingpixels.flamingo.api.bcb.BreadcrumbBarCallBack;
import org.pushingpixels.flamingo.api.bcb.BreadcrumbItem;
import org.pushingpixels.flamingo.api.bcb.JBreadcrumbBar;
import org.pushingpixels.flamingo.api.common.StringValuePair;
/**
* Breadcrumb bar that allows browsing the local file system.
*
* @author Kirill Grouchnikov
* @author Brian Young
*/
public class BreadcrumbFileSelector extends JBreadcrumbBar<File> {
/**
* If <code>true</code>, the path selectors will use native icons.
*/
protected boolean useNativeIcons;
/**
* Local file system specific implementation of the
* {@link BreadcrumbBarCallBack}.
*
* @author Kirill Grouchnikov
*/
public static class DirCallback extends BreadcrumbBarCallBack<File> {
/**
* File system view.
*/
protected FileSystemView fsv;
/**
* If <code>true</code>, the path selectors will use native icons.
*/
protected boolean useNativeIcons;
/**
* Creates a new callback.
*
* @param useNativeIcons
* If <code>true</code>, the path selectors will use native
* icons.
*/
public DirCallback(boolean useNativeIcons) {
this(FileSystemView.getFileSystemView(), useNativeIcons);
}
/**
* Creates a new callback.
*
* @param fileSystemView
* File system view to use.
* @param useNativeIcons
* If <code>true</code>, the path selectors will use native
* icons.
*/
public DirCallback(FileSystemView fileSystemView, boolean useNativeIcons) {
this.fsv = fileSystemView;
this.useNativeIcons = useNativeIcons;
}
/*
* (non-Javadoc)
*
* @see org.jvnet.flamingo.bcb.BreadcrumbBarCallBack#setup()
*/
@Override
public void setup() {
}
@Override
public List<StringValuePair<File>> getPathChoices(
List<BreadcrumbItem<File>> path) {
synchronized (fsv) {
if (path == null) {
LinkedList<StringValuePair<File>> bRoots = new LinkedList<StringValuePair<File>>();
for (File root : fsv.getRoots()) {
if (fsv.isHiddenFile(root))
continue;
String systemName = fsv.getSystemDisplayName(root);
if (systemName.length() == 0)
systemName = root.getAbsolutePath();
StringValuePair<File> rootPair = new StringValuePair<File>(
systemName, root);
if (useNativeIcons)
rootPair.set("icon", fsv.getSystemIcon(root));
bRoots.add(rootPair);
}
return bRoots;
}
if (path.size() == 0)
return null;
File lastInPath = path.get(path.size() - 1).getData();
if (!lastInPath.exists())
return new ArrayList<StringValuePair<File>>();
if (!lastInPath.isDirectory())
return null;
LinkedList<StringValuePair<File>> lResult = new LinkedList<StringValuePair<File>>();
for (File child : lastInPath.listFiles()) {
// ignore regular files and hidden directories
if (!child.isDirectory())
continue;
if (fsv.isHiddenFile(child))
continue;
String childFileName = fsv.getSystemDisplayName(child);
if ((childFileName == null) || childFileName.isEmpty())
childFileName = child.getName();
StringValuePair<File> pair = new StringValuePair<File>(
childFileName, child);
if (useNativeIcons)
pair.set("icon", fsv.getSystemIcon(child));
lResult.add(pair);
}
Collections.sort(lResult,
new Comparator<StringValuePair<File>>() {
@Override
public int compare(StringValuePair<File> o1,
StringValuePair<File> o2) {
String key1 = fsv.isFileSystemRoot(o1
.getValue()) ? o1.getValue()
.getAbsolutePath() : o1.getKey();
String key2 = fsv.isFileSystemRoot(o2
.getValue()) ? o2.getValue()
.getAbsolutePath() : o2.getKey();
return key1.toLowerCase().compareTo(
key2.toLowerCase());
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
});
return lResult;
}
}
/*
* (non-Javadoc)
*
* @see
* org.jvnet.flamingo.bcb.BreadcrumbBarCallBack#getLeafs(org.jvnet.flamingo
* .bcb.BreadcrumbItem<T>[])
*/
@Override
public List<StringValuePair<File>> getLeafs(
List<BreadcrumbItem<File>> path) {
synchronized (fsv) {
if ((path == null) || (path.size() == 0))
return null;
File lastInPath = path.get(path.size() - 1).getData();
if (!lastInPath.exists())
return new ArrayList<StringValuePair<File>>();
if (!lastInPath.isDirectory())
return null;
LinkedList<StringValuePair<File>> lResult = new LinkedList<StringValuePair<File>>();
for (File child : lastInPath.listFiles()) {
// ignore directories and hidden directories
if (child.isDirectory())
continue;
if (fsv.isHiddenFile(child))
continue;
String childFileName = fsv.getSystemDisplayName(child);
if ((childFileName == null) || childFileName.isEmpty())
childFileName = child.getName();
StringValuePair<File> pair = new StringValuePair<File>(
childFileName, child);
if (useNativeIcons)
pair.set("icon", fsv.getSystemIcon(child));
lResult.add(pair);
}
Collections.sort(lResult,
new Comparator<StringValuePair<File>>() {
@Override
public int compare(StringValuePair<File> o1,
StringValuePair<File> o2) {
return o1.getKey().toLowerCase().compareTo(
o2.getKey().toLowerCase());
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
});
return lResult;
}
}
/*
* (non-Javadoc)
*
* @see
* org.jvnet.flamingo.bcb.BreadcrumbBarCallBack#getLeafContent(java.
* lang.Object)
*/
@Override
public InputStream getLeafContent(File leaf) {
try {
return new FileInputStream(leaf);
} catch (FileNotFoundException fnfe) {
return null;
}
}
}
/**
* Creates a new breadcrumb bar file selector that uses native icons and the
* default file system view.
*/
public BreadcrumbFileSelector() {
this(true);
}
/**
* Creates a new breadcrumb bar file selector that uses the default file
* system view.
*
* @param useNativeIcons
* If <code>true</code>, the path selectors will use native
* icons.
*/
public BreadcrumbFileSelector(boolean useNativeIcons) {
this(FileSystemView.getFileSystemView(), useNativeIcons);
}
/**
* Creates a new breadcrumb bar file selector.
*
* @param fileSystemView
* File system view.
* @param useNativeIcons
* If <code>true</code>, the path selectors will use native
* icons.
*/
public BreadcrumbFileSelector(FileSystemView fileSystemView,
boolean useNativeIcons) {
super(new DirCallback(fileSystemView, useNativeIcons));
this.useNativeIcons = useNativeIcons;
}
/**
* Sets indication whether the path selectors should use native icons.
*
* @param useNativeIcons
* If <code>true</code>, the path selectors will use native
* icons.
*/
public void setUseNativeIcons(boolean useNativeIcons) {
this.useNativeIcons = useNativeIcons;
}
/**
* Sets the selected path based of the specified file. If this file is
* either <code>null</code> or not a directory, the home directory is
* selected.
*
* @param dir
* Points to a directory to be selected.
*/
public void setPath(File dir) {
// System.out.println(dir.getAbsolutePath());
FileSystemView fsv = FileSystemView.getFileSystemView();
synchronized (fsv) {
if ((dir == null) || !dir.isDirectory()) {
dir = fsv.getHomeDirectory();
}
ArrayList<BreadcrumbItem<File>> path = new ArrayList<BreadcrumbItem<File>>();
File parent = dir;
BreadcrumbItem<File> bci = new BreadcrumbItem<File>(fsv
.getSystemDisplayName(dir), dir);
bci.setIcon(fsv.getSystemIcon(dir));
path.add(bci);
while (true) {
parent = fsv.getParentDirectory(parent);
if (parent == null)
break;
bci = new BreadcrumbItem<File>(
fsv.getSystemDisplayName(parent), parent);
bci.setIcon(fsv.getSystemIcon(parent));
path.add(bci);
}
Collections.reverse(path);
this.setPath(path);
}
}
}