Added: pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowser.java URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowser.java?rev=1486223&view=auto ============================================================================== --- pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowser.java (added) +++ pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowser.java Fri May 24 21:22:39 2013 @@ -0,0 +1,477 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.pivot.wtk; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.commons.vfs2.FileName; +import org.apache.commons.vfs2.FileObject; +import org.apache.commons.vfs2.FileSystemException; +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.commons.vfs2.FileType; +import org.apache.commons.vfs2.VFS; +import org.apache.pivot.collections.ArrayList; +import org.apache.pivot.collections.Sequence; +import org.apache.pivot.collections.immutable.ImmutableList; +import org.apache.pivot.io.FileObjectList; +import org.apache.pivot.util.Filter; +import org.apache.pivot.util.ListenerList; + +/** + * A file browser that uses the Apache Commons VFS (Virtual File System) + * to be able to browse local and remote file systems, and browse inside + * of .zip, .tar, etc. archives as well. + */ +public class VFSBrowser extends Container { + /** + * Commons VFS browser skin interface. + */ + public interface Skin extends org.apache.pivot.wtk.Skin { + public FileObject getFileAt(int x, int y); + } + + private static final URI USER_HOME = new File(System.getProperty("user.home")).toURI(); + + private static class FileBrowserListenerList extends WTKListenerList<VFSBrowserListener> + implements VFSBrowserListener { + @Override + public void managerChanged(VFSBrowser fileBrowser, FileSystemManager previousManager) { + for (VFSBrowserListener listener : this) { + listener.managerChanged(fileBrowser, previousManager); + } + } + + @Override + public void rootDirectoryChanged(VFSBrowser fileBrowser, FileObject previousRootDirectory) { + for (VFSBrowserListener listener : this) { + listener.rootDirectoryChanged(fileBrowser, previousRootDirectory); + } + } + + @Override + public void selectedFileAdded(VFSBrowser fileBrowser, FileObject file) { + for (VFSBrowserListener listener : this) { + listener.selectedFileAdded(fileBrowser, file); + } + } + + @Override + public void selectedFileRemoved(VFSBrowser fileBrowser, FileObject file) { + for (VFSBrowserListener listener : this) { + listener.selectedFileRemoved(fileBrowser, file); + } + } + + @Override + public void selectedFilesChanged(VFSBrowser fileBrowser, + Sequence<FileObject> previousSelectedFiles) { + for (VFSBrowserListener listener : this) { + listener.selectedFilesChanged(fileBrowser, previousSelectedFiles); + } + } + + @Override + public void multiSelectChanged(VFSBrowser fileBrowser) { + for (VFSBrowserListener listener : this) { + listener.multiSelectChanged(fileBrowser); + } + } + + @Override + public void disabledFileFilterChanged(VFSBrowser fileBrowser, + Filter<FileObject> previousDisabledFileFilter) { + for (VFSBrowserListener listener : this) { + listener.disabledFileFilterChanged(fileBrowser, previousDisabledFileFilter); + } + } + } + + private FileSystemManager manager; + private FileName baseFileName; + private FileObject rootDirectory; + private FileObjectList selectedFiles = new FileObjectList(); + private boolean multiSelect = false; + private Filter<FileObject> disabledFileFilter = null; + + private FileBrowserListenerList fileBrowserListeners = new FileBrowserListenerList(); + + /** + * Creates a new VFSBrowser + * <p> + * Note that this version set by default mode to open. + */ + public VFSBrowser() + throws FileSystemException + { + this(null, USER_HOME); + } + + /** + * Creates a new VFSBrowser + * <p> + * Note that this version of the constructor must be used when a custom root folder (that + * may include a completely different URI scheme) has to be set. + * + * @param manager + * The virtual file system we're going to manage. + * @param rootFolder + * The root folder full name. + */ + public VFSBrowser(FileSystemManager manager, URI rootFolder) + throws FileSystemException + { + if (rootFolder == null) { + throw new IllegalArgumentException(); + } + + if (manager == null) { + this.manager = VFS.getManager(); + } else { + this.manager = manager; + } + FileObject baseFile = this.manager.getBaseFile(); + if (baseFile != null) { + baseFileName = baseFile.getName(); + } + rootDirectory = this.manager.resolveFile(rootFolder); + if (rootDirectory.getType() != FileType.FOLDER) { + throw new IllegalArgumentException(); + } + installSkin(VFSBrowser.class); + } + + /** + * Creates a new VFSBrowser + * <p> + * Note that this version of the constructor must be used when a custom root folder has to be set. + * + * @param manager + * The virtual file system we're going to manage. + * @param rootFolder + * The root folder full name. + */ + public VFSBrowser(FileSystemManager manager, String rootFolder) + throws FileSystemException + { + if (rootFolder == null) { + throw new IllegalArgumentException(); + } + + if (manager == null) { + this.manager = VFS.getManager(); + } else { + this.manager = manager; + } + FileObject baseFile = this.manager.getBaseFile(); + if (baseFile != null) { + baseFileName = baseFile.getName(); + } + rootDirectory = this.manager.resolveFile(rootFolder); + if (rootDirectory.getType() != FileType.FOLDER) { + throw new IllegalArgumentException(); + } + installSkin(VFSBrowser.class); + } + + /** + * Returns the current file system manager. + * + * @return + * The current file system manager. + */ + public FileSystemManager getManager() { + return manager; + } + + /** + * Returns the current root directory. + * + * @return + * The current root directory. + */ + public FileObject getRootDirectory() { + return rootDirectory; + } + + /** + * Sets the root directory from a string. Clears any + * existing file selection. + * + * @param rootDirectory + */ + public void setRootDirectory(String rootDirectory) + throws FileSystemException + { + setRootDirectory(manager.resolveFile(rootDirectory)); + } + + /** + * Sets the root directory. Clears any existing file selection. + * + * @param rootDirectory + */ + public void setRootDirectory(FileObject rootDirectory) + throws FileSystemException + { + if (rootDirectory == null + || rootDirectory.getType() != FileType.FOLDER) { + throw new IllegalArgumentException(); + } + + if (rootDirectory.exists()) { + FileObject previousRootDirectory = this.rootDirectory; + + if (!rootDirectory.equals(previousRootDirectory)) { + this.rootDirectory = rootDirectory; + selectedFiles.clear(); + fileBrowserListeners.rootDirectoryChanged(this, previousRootDirectory); + } + } else { + setRootDirectory(rootDirectory.getParent()); + } + } + + /** + * Adds a file to the file selection. + * + * @param file + * + * @return + * <tt>true</tt> if the file was added; <tt>false</tt> if it was already + * selected. + */ + public boolean addSelectedFile(FileObject file) + throws FileSystemException + { + if (file == null) { + throw new IllegalArgumentException(); + } + + // TODO: is this a good way to do this? + //if (file.isAbsolute()) { + if (baseFileName != null && baseFileName.isDescendent(file.getName())) { + if (!file.getParent().equals(rootDirectory)) { + throw new IllegalArgumentException(); + } + } else { + file = manager.resolveFile(rootDirectory, file.getName().getPath()); + } + + int index = selectedFiles.add(file); + if (index != -1) { + fileBrowserListeners.selectedFileAdded(this, file); + } + + return (index != -1); + } + + /** + * Removes a file from the file selection. + * + * @param file + * + * @return + * <tt>true</tt> if the file was removed; <tt>false</tt> if it was not + * already selected. + */ + public boolean removeSelectedFile(FileObject file) { + if (file == null) { + throw new IllegalArgumentException(); + } + + int index = selectedFiles.remove(file); + if (index != -1) { + fileBrowserListeners.selectedFileRemoved(this, file); + } + + return (index != -1); + } + + /** + * When in single-select mode, returns the currently selected file. + * + * @return + * The currently selected file. + */ + public FileObject getSelectedFile() { + if (multiSelect) { + throw new IllegalStateException("File browser is not in single-select mode."); + } + + return (selectedFiles.getLength() == 0) ? null : selectedFiles.get(0); + } + + /** + * Sets the selection to a single file. + * + * @param file + */ + public void setSelectedFile(FileObject file) + throws FileSystemException + { + if (file == null) { + clearSelection(); + } else { + // TODO: adequate replacement for "isAbsolute"? + //if (file.isAbsolute()) { + if (baseFileName != null && baseFileName.isDescendent(file.getName())) { + setRootDirectory(file.getParent()); + } + + setSelectedFiles(new ArrayList<FileObject>(file)); + } + } + + /** + * Returns the currently selected files. + * + * @return + * An immutable list containing the currently selected files. Note that the returned + * list is a wrapper around the actual selection, not a copy. Any changes made to the + * selection state will be reflected in the list, but events will not be fired. + */ + public ImmutableList<FileObject> getSelectedFiles() { + return new ImmutableList<FileObject>(selectedFiles); + } + + /** + * Sets the selected files. + * + * @param selectedFiles + * The files to select. + * + * @return + * The files that were selected, with duplicates eliminated. + */ + public Sequence<FileObject> setSelectedFiles(Sequence<FileObject> selectedFiles) + throws FileSystemException + { + if (selectedFiles == null) { + throw new IllegalArgumentException("selectedFiles is null."); + } + + if (!multiSelect + && selectedFiles.getLength() > 1) { + throw new IllegalArgumentException("Multi-select is not enabled."); + } + + // Update the selection + Sequence<FileObject> previousSelectedFiles = getSelectedFiles(); + + FileObjectList fileList = new FileObjectList(); + for (int i = 0, n = selectedFiles.getLength(); i < n; i++) { + FileObject file = selectedFiles.get(i); + + if (file == null) { + throw new IllegalArgumentException("file is null."); + } + + // TODO: is this correct? + //if (!file.isAbsolute()) { + if (baseFileName == null || !baseFileName.isDescendent(file.getName())) { + file = manager.resolveFile(rootDirectory, file.getName().getPath()); + } + + // TODO: don't do this for now -- revisit later + //if (!file.getParent().equals(rootDirectory)) { + // throw new IllegalArgumentException(); + //} + + fileList.add(file); + } + + this.selectedFiles = fileList; + + // Notify listeners + fileBrowserListeners.selectedFilesChanged(this, previousSelectedFiles); + + return getSelectedFiles(); + } + + /** + * Clears the selection. + */ + public void clearSelection() + throws FileSystemException + { + setSelectedFiles(new ArrayList<FileObject>()); + } + + public boolean isFileSelected(FileObject file) { + return (selectedFiles.indexOf(file) != -1); + } + + /** + * Returns the file browser's multi-select state. + */ + public boolean isMultiSelect() { + return multiSelect; + } + + /** + * Sets the file browser's multi-select state. + * + * @param multiSelect + * <tt>true</tt> if multi-select is enabled; <tt>false</tt>, otherwise. + */ + public void setMultiSelect(boolean multiSelect) { + if (this.multiSelect != multiSelect) { + // Clear any existing selection + selectedFiles.clear(); + + this.multiSelect = multiSelect; + + fileBrowserListeners.multiSelectChanged(this); + } + } + + /** + * Returns the current file filter. + * + * @return + * The current file filter, or <tt>null</tt> if no filter is set. + */ + public Filter<FileObject> getDisabledFileFilter() { + return disabledFileFilter; + } + + /** + * Sets the file filter. + * + * @param disabledFileFilter + * The file filter to use, or <tt>null</tt> for no filter. + */ + public void setDisabledFileFilter(Filter<FileObject> disabledFileFilter) { + Filter<FileObject> previousDisabledFileFilter = this.disabledFileFilter; + + if (previousDisabledFileFilter != disabledFileFilter) { + this.disabledFileFilter = disabledFileFilter; + fileBrowserListeners.disabledFileFilterChanged(this, previousDisabledFileFilter); + } + } + + public FileObject getFileAt(int x, int y) { + VFSBrowser.Skin fileBrowserSkin = (VFSBrowser.Skin)getSkin(); + return fileBrowserSkin.getFileAt(x, y); + } + + public ListenerList<VFSBrowserListener> getFileBrowserListeners() { + return fileBrowserListeners; + } +}
Added: pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserListener.java URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserListener.java?rev=1486223&view=auto ============================================================================== --- pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserListener.java (added) +++ pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserListener.java Fri May 24 21:22:39 2013 @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.pivot.wtk; + +import org.apache.commons.vfs2.FileObject; +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.pivot.collections.Sequence; +import org.apache.pivot.util.Filter; + +/** + * Commons VFS browser listener interface. + */ +public interface VFSBrowserListener { + /** + * Commons VFS browser listener adapter. + */ + public static class Adapter implements VFSBrowserListener { + @Override + public void managerChanged(VFSBrowser fileBrowser, FileSystemManager previousManager) { + // empty block + } + + @Override + public void rootDirectoryChanged(VFSBrowser fileBrowser, FileObject previousRootDirectory) { + // empty block + } + + @Override + public void selectedFileAdded(VFSBrowser fileBrowser, FileObject file) { + // empty block + } + + @Override + public void selectedFileRemoved(VFSBrowser fileBrowser, FileObject file) { + // empty block + } + + @Override + public void selectedFilesChanged(VFSBrowser fileBrowser, + Sequence<FileObject> previousSelectedFiles) { + // empty block + } + + @Override + public void multiSelectChanged(VFSBrowser fileBrowser) { + // empty block + } + + @Override + public void disabledFileFilterChanged(VFSBrowser fileBrowser, + Filter<FileObject> previousDisabledFileFilter) { + // empty block + } + } + + /** + * Called when a file browser's FileSystemManager has changed, + * (such as when a nested VirtualFileSystem is opened). + * + * @param fileBrowser + * @param previousManager + */ + public void managerChanged(VFSBrowser fileBrowser, FileSystemManager previousManager); + + /** + * Called when a file browser's root directory has changed. + * + * @param fileBrowser + * @param previousRootDirectory + */ + public void rootDirectoryChanged(VFSBrowser fileBrowser, FileObject previousRootDirectory); + + /** + * Called when a file has been added to a file browser's selection. + * + * @param fileBrowser + * @param file + */ + public void selectedFileAdded(VFSBrowser fileBrowser, FileObject file); + + /** + * Called when a file has been removed from a file browser's selection. + * + * @param fileBrowser + * @param file + */ + public void selectedFileRemoved(VFSBrowser fileBrowser, FileObject file); + + /** + * Called when a file browser's selection state has been reset. + * + * @param fileBrowser + * @param previousSelectedFiles + */ + public void selectedFilesChanged(VFSBrowser fileBrowser, + Sequence<FileObject> previousSelectedFiles); + + /** + * Called when a file browser's multi-select flag has changed. + * + * @param fileBrowser + */ + public void multiSelectChanged(VFSBrowser fileBrowser); + + /** + * Called when a file browser's file filter has changed. + * + * @param fileBrowser + * @param previousDisabledFileFilter + */ + public void disabledFileFilterChanged(VFSBrowser fileBrowser, + Filter<FileObject> previousDisabledFileFilter); +} Added: pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserSheet.java URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserSheet.java?rev=1486223&view=auto ============================================================================== --- pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserSheet.java (added) +++ pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserSheet.java Fri May 24 21:22:39 2013 @@ -0,0 +1,400 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.pivot.wtk; + +import org.apache.commons.vfs2.FileName; +import org.apache.commons.vfs2.FileObject; +import org.apache.commons.vfs2.FileSystemException; +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.commons.vfs2.FileType; +import org.apache.commons.vfs2.VFS; +import org.apache.pivot.collections.ArrayList; +import org.apache.pivot.collections.Sequence; +import org.apache.pivot.collections.immutable.ImmutableList; +import org.apache.pivot.io.FileObjectList; +import org.apache.pivot.util.Filter; +import org.apache.pivot.util.ListenerList; + +/** + * A file browser sheet that uses the Apache Commons VFS (Virtual File System) + * to be able to browse local and remote file systems, and browse inside + * of .zip, .tar, etc. archives as well. + */ +public class VFSBrowserSheet extends Sheet { + /** + * Enumeration defining supported modes. + */ + public enum Mode { + OPEN, + OPEN_MULTIPLE, + SAVE_AS, + SAVE_TO + } + + private static final String USER_HOME = System.getProperty("user.home"); + + private static class FileBrowserSheetListenerList + extends WTKListenerList<VFSBrowserSheetListener> + implements VFSBrowserSheetListener { + @Override + public void managerChanged(VFSBrowserSheet fileBrowserSheet, + FileSystemManager previousManager) { + for (VFSBrowserSheetListener listener : this) { + listener.managerChanged(fileBrowserSheet, previousManager); + } + } + + @Override + public void modeChanged(VFSBrowserSheet fileBrowserSheet, + VFSBrowserSheet.Mode previousMode) { + for (VFSBrowserSheetListener listener : this) { + listener.modeChanged(fileBrowserSheet, previousMode); + } + } + + @Override + public void rootDirectoryChanged(VFSBrowserSheet fileBrowserSheet, + FileObject previousRootDirectory) { + for (VFSBrowserSheetListener listener : this) { + listener.rootDirectoryChanged(fileBrowserSheet, previousRootDirectory); + } + } + + @Override + public void selectedFilesChanged(VFSBrowserSheet fileBrowserSheet, + Sequence<FileObject> previousSelectedFiles) { + for (VFSBrowserSheetListener listener : this) { + listener.selectedFilesChanged(fileBrowserSheet, previousSelectedFiles); + } + } + + @Override + public void disabledFileFilterChanged(VFSBrowserSheet fileBrowserSheet, + Filter<FileObject> previousDisabledFileFilter) { + for (VFSBrowserSheetListener listener : this) { + listener.disabledFileFilterChanged(fileBrowserSheet, + previousDisabledFileFilter); + } + } + } + + private Mode mode; + private FileSystemManager manager; + private FileName baseFileName; + private FileObject rootDirectory; + private FileObjectList selectedFiles = new FileObjectList(); + private Filter<FileObject> disabledFileFilter = null; + + private FileBrowserSheetListenerList fileBrowserSheetListeners = new FileBrowserSheetListenerList(); + + /** + * Creates a new VFSBrowserSheet + * <p> + * Note that this version set by default mode to open and user home as root folder. + */ + public VFSBrowserSheet() + throws FileSystemException + { + this(Mode.OPEN); + } + + /** + * Creates a new VFSBrowserSheet + * <p> + * Note that this version set by default the user home as root folder. + * + * @param mode + * The mode for opening the sheet. + * @see Mode + */ + public VFSBrowserSheet(Mode mode) + throws FileSystemException + { + this(mode, USER_HOME); + } + + /** + * Creates a new VFSBrowserSheet + * <p> + * Note that this version of the constructor must be used when a custom root folder has to be set. + * + * @param mode + * The mode for opening the sheet. + * @see Mode + * + * @param rootFolder + * The root folder full name. + */ + public VFSBrowserSheet(Mode mode, String rootFolder) + throws FileSystemException + { + this(null, mode, rootFolder); + } + + /** + * Creates a new VFSBrowserSheet + * <p> + * Note that this version of the constructor must be used when a custom root folder has to be set. + * + * @param manager + * The VFS FileSystemManager that we will be browsing. If <tt>null</tt> the default (local) will + * be used. + * + * @param mode + * The mode for opening the sheet. + * @see Mode + * + * @param rootFolder + * The root folder full name. + */ + public VFSBrowserSheet(FileSystemManager manager, Mode mode, String rootFolder) + throws FileSystemException + { + if (mode == null) { + throw new IllegalArgumentException(); + } + + if (rootFolder == null) { + throw new IllegalArgumentException(); + } + + setManager(manager); + + this.mode = mode; + + setRootFolder(rootFolder); + + installSkin(VFSBrowserSheet.class); + } + + public FileSystemManager getManager() { + return manager; + } + + public void setManager(FileSystemManager manager) + throws FileSystemException + { + FileSystemManager previousManager = this.manager; + + if (manager == null) { + this.manager = VFS.getManager(); + } else { + this.manager = manager; + } + FileObject baseFile = this.manager.getBaseFile(); + if (baseFile != null) { + baseFileName = baseFile.getName(); + } + + if (previousManager != null && previousManager != this.manager) { + fileBrowserSheetListeners.managerChanged(this, previousManager); + } + } + + public FileName getBaseFileName() { + return baseFileName; + } + + public Mode getMode() { + return mode; + } + + public void setMode(Mode mode) { + if (mode == null) { + throw new IllegalArgumentException(); + } + + Mode previousMode = this.mode; + + if (previousMode != mode) { + this.mode = mode; + fileBrowserSheetListeners.modeChanged(this, previousMode); + } + } + + public FileObject getRootDirectory() { + return rootDirectory; + } + + // set the root folder but without firing events + public void setRootFolder(String rootFolder) + throws FileSystemException + { + if (rootFolder == null) { + throw new IllegalArgumentException(); + } + + rootDirectory = manager.resolveFile(rootFolder); + if (rootDirectory.getType() != FileType.FOLDER) { + throw new IllegalArgumentException(); + } + + } + + public void setRootDirectory(String rootDirectory) + throws FileSystemException + { + setRootDirectory(manager.resolveFile(rootDirectory)); + } + + public void setRootDirectory(FileObject rootDirectory) + throws FileSystemException + { + if (rootDirectory == null + || rootDirectory.getType() != FileType.FOLDER) { + throw new IllegalArgumentException(); + } + + if (rootDirectory.exists()) { + FileObject previousRootDirectory = this.rootDirectory; + + if (!rootDirectory.equals(previousRootDirectory)) { + this.rootDirectory = rootDirectory; + selectedFiles.clear(); + fileBrowserSheetListeners.rootDirectoryChanged(this, previousRootDirectory); + } + } else { + setRootDirectory(rootDirectory.getParent()); + } + } + + /** + * When in single-select mode, returns the currently selected file. + * + * @return + * The currently selected file. + */ + public FileObject getSelectedFile() { + if (mode == Mode.OPEN_MULTIPLE) { + throw new IllegalStateException("File browser sheet is not in single-select mode."); + } + + return (selectedFiles.getLength() == 0) ? null : selectedFiles.get(0); + } + + /** + * Sets the selection to a single file. + * + * @param file + */ + public void setSelectedFile(FileObject file) + throws FileSystemException + { + if (file == null) { + clearSelection(); + } else { + // TODO: will this work right? + //if (file.isAbsolute()) { + if (baseFileName != null && baseFileName.isDescendent(file.getName())) { + setRootDirectory(file.getParent()); + } + + setSelectedFiles(new ArrayList<FileObject>(file)); + } + } + + /** + * Returns the currently selected files. + * + * @return + * An immutable list containing the currently selected files. Note that the returned + * list is a wrapper around the actual selection, not a copy. Any changes made to the + * selection state will be reflected in the list, but events will not be fired. + */ + public ImmutableList<FileObject> getSelectedFiles() { + return new ImmutableList<FileObject>(selectedFiles); + } + + /** + * Sets the selected files. + * + * @param selectedFiles + * The files to select. + * + * @return + * The files that were selected, with duplicates eliminated. + */ + public Sequence<FileObject> setSelectedFiles(Sequence<FileObject> selectedFiles) + throws FileSystemException + { + if (selectedFiles == null) { + throw new IllegalArgumentException("selectedFiles is null."); + } + + if (mode != Mode.OPEN_MULTIPLE + && selectedFiles.getLength() > 1) { + throw new IllegalArgumentException("Multi-select is not enabled."); + } + + // Update the selection + Sequence<FileObject> previousSelectedFiles = getSelectedFiles(); + + FileObjectList fileList = new FileObjectList(); + for (int i = 0, n = selectedFiles.getLength(); i < n; i++) { + FileObject file = selectedFiles.get(i); + + if (file == null) { + throw new IllegalArgumentException("file is null."); + } + + // TODO: is this correct? + //if (!file.isAbsolute()) { + if (baseFileName == null || !baseFileName.isDescendent(file.getName())) { + file = manager.resolveFile(rootDirectory, file.getName().getPath()); + } + + if (!file.getParent().equals(rootDirectory)) { + throw new IllegalArgumentException(); + } + + fileList.add(file); + } + + this.selectedFiles = fileList; + + // Notify listeners + fileBrowserSheetListeners.selectedFilesChanged(this, previousSelectedFiles); + + return getSelectedFiles(); + } + + /** + * Clears the selection. + */ + public void clearSelection() + throws FileSystemException + { + setSelectedFiles(new ArrayList<FileObject>()); + } + + public Filter<FileObject> getDisabledFileFilter() { + return disabledFileFilter; + } + + public void setDisabledFileFilter(Filter<FileObject> disabledFileFilter) { + Filter<FileObject> previousDisabledFileFilter = this.disabledFileFilter; + + if (previousDisabledFileFilter != disabledFileFilter) { + this.disabledFileFilter = disabledFileFilter; + fileBrowserSheetListeners.disabledFileFilterChanged(this, previousDisabledFileFilter); + } + } + + public ListenerList<VFSBrowserSheetListener> getFileBrowserSheetListeners() { + return fileBrowserSheetListeners; + } +} Added: pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserSheetListener.java URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserSheetListener.java?rev=1486223&view=auto ============================================================================== --- pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserSheetListener.java (added) +++ pivot/trunk/wtk/src/org/apache/pivot/wtk/VFSBrowserSheetListener.java Fri May 24 21:22:39 2013 @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.pivot.wtk; + +import org.apache.commons.vfs2.FileObject; +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.pivot.collections.Sequence; +import org.apache.pivot.util.Filter; + +/** + * Commons VFS browser sheet listener interface. + */ +public interface VFSBrowserSheetListener { + /** + * Commons VFS browser sheet listener adapter. + */ + public static class Adapter implements VFSBrowserSheetListener { + @Override + public void managerChanged(VFSBrowserSheet fileBrowserSheet, + FileSystemManager previousManager) { + // empty block + } + + @Override + public void modeChanged(VFSBrowserSheet fileBrowserSheet, + VFSBrowserSheet.Mode previousMode) { + // empty block + } + + @Override + public void rootDirectoryChanged(VFSBrowserSheet fileBrowserSheet, + FileObject previousRootDirectory) { + // empty block + } + + @Override + public void selectedFilesChanged(VFSBrowserSheet fileBrowserSheet, + Sequence<FileObject> previousSelectedFiles) { + // empty block + } + + @Override + public void disabledFileFilterChanged(VFSBrowserSheet fileBrowserSheet, + Filter<FileObject> previousDisabledFileFilter) { + // empty block + } + } + + /** + * Called when a file browser's file system manager has changed + * (as when browsing into a new virtual file system). + * + * @param fileBrowserSheet + * @param previousManager + */ + public void managerChanged(VFSBrowserSheet fileBrowserSheet, FileSystemManager previousManager); + + /** + * Called when a file browser sheet's mode has changed. + * + * @param fileBrowserSheet + * @param previousMode + */ + public void modeChanged(VFSBrowserSheet fileBrowserSheet, VFSBrowserSheet.Mode previousMode); + + /** + * Called when a file browser sheet's root directory has changed. + * + * @param fileBrowserSheet + * @param previousRootDirectory + */ + public void rootDirectoryChanged(VFSBrowserSheet fileBrowserSheet, + FileObject previousRootDirectory); + + /** + * Called when a file browser sheet's selection state has been reset. + * + * @param fileBrowserSheet + * @param previousSelectedFiles + */ + public void selectedFilesChanged(VFSBrowserSheet fileBrowserSheet, + Sequence<FileObject> previousSelectedFiles); + + /** + * Called when a file browser sheet's disabled file filter has changed. + * + * @param fileBrowserSheet + * @param previousDisabledFileFilter + */ + public void disabledFileFilterChanged(VFSBrowserSheet fileBrowserSheet, + Filter<FileObject> previousDisabledFileFilter); +} Added: pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/VFSBrowserSkin.java URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/VFSBrowserSkin.java?rev=1486223&view=auto ============================================================================== --- pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/VFSBrowserSkin.java (added) +++ pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/VFSBrowserSkin.java Fri May 24 21:22:39 2013 @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.pivot.wtk.skin; + +import org.apache.pivot.wtk.Component; +import org.apache.pivot.wtk.VFSBrowser; +import org.apache.pivot.wtk.VFSBrowserListener; +import org.apache.pivot.wtk.skin.ContainerSkin; + +/** + * Abstract base class for Commons VFS browser skins. + */ +public abstract class VFSBrowserSkin extends ContainerSkin + implements VFSBrowser.Skin, VFSBrowserListener { + @Override + public void install(Component component) { + super.install(component); + + VFSBrowser fileBrowser = (VFSBrowser)component; + fileBrowser.getFileBrowserListeners().add(this); + } +}