/******************************************************************************* * Copyright (c) 2004, 2010 BREDEX GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.client.ui.rcp.dialogs; import java.util.List; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.ListViewer; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jubula.client.ui.rcp.i18n.Messages; import org.eclipse.jubula.client.ui.rcp.utils.RemoteFileStore; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; import org.eclipse.ui.dialogs.ISelectionStatusValidator; import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; import org.eclipse.ui.internal.ide.dialogs.IDEResourceInfoUtils; import org.eclipse.ui.internal.ide.dialogs.IFileStoreFilter; /** * Selection dialog to select files and/or folders on a remote * the file system. Use setInput to set input to an IFileStore that * points to a folder. * */ public class RemoteFileBrowserDialog extends ElementTreeSelectionDialog { /** * Label provider for IFileStore objects. */ private static class FileLabelProvider extends LabelProvider { /** folder icon */ private static final Image IMG_FOLDER = PlatformUI.getWorkbench() .getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER); /** file icon */ private static final Image IMG_FILE = PlatformUI.getWorkbench() .getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE); /** * {@inheritDoc} */ public Image getImage(Object element) { if (element instanceof IFileStore) { IFileStore curr = (IFileStore) element; if (curr.fetchInfo().isDirectory()) { return IMG_FOLDER; } return IMG_FILE; } return null; } /** * {@inheritDoc} */ public String getText(Object element) { if (element instanceof IFileStore) { return ((IFileStore) element).getName(); } return super.getText(element); } } /** * Content provider for IFileStore objects. */ private static class FileContentProvider implements ITreeContentProvider { /** empty result */ private static final Object[] EMPTY = new Object[0]; /** filter */ private IFileStoreFilter m_fileFilter; /** * Creates a new instance of the receiver. * * @param showFiles * <code>true</code> files and folders are returned by the * receiver. <code>false</code> only folders are returned. */ public FileContentProvider(final boolean showFiles) { m_fileFilter = new IFileStoreFilter() { /* * (non-Javadoc) * * @see org.eclipse.ui.internal.ide.dialogs.IFileStoreFilter#accept(org.eclipse.core.filesystem.IFileStore) */ public boolean accept(IFileStore file) { if (!file.fetchInfo().exists()) { return false; } return !(!file.fetchInfo().isDirectory() && !showFiles); } }; } /** * {@inheritDoc} */ public Object[] getChildren(Object parentElement) { if (parentElement instanceof IFileStore) { IFileStore[] children = IDEResourceInfoUtils.listFileStores( (IFileStore) parentElement, m_fileFilter, new NullProgressMonitor()); if (children != null) { return children; } } return EMPTY; } /** * * {@inheritDoc} */ public Object getParent(Object element) { if (element instanceof IFileStore) { return ((IFileStore) element).getParent(); } return null; } /** * * {@inheritDoc} */ public boolean hasChildren(Object element) { return getChildren(element).length > 0; } /** * * {@inheritDoc} */ public Object[] getElements(Object element) { return getChildren(element); } /** * * {@inheritDoc} */ public void dispose() { // nothing here } /** * * {@inheritDoc} */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // nothing here } } /** * Viewer sorter that places folders first, then files. */ private static class FileViewerSorter extends ViewerComparator { /** * * {@inheritDoc} */ public int category(Object element) { if (element instanceof IFileStore && !((IFileStore) element).fetchInfo().isDirectory()) { return 1; } return 0; } } /** * Validates the selection based on the multi select and folder setting. */ private static class FileSelectionValidator implements ISelectionStatusValidator { /** allow multiple selection */ private boolean m_multiSelect; /** accept folders */ private boolean m_acceptFolders; /** * Creates a new instance of the receiver. * * @param multiSelect * <code>true</code> if multi selection is allowed. * <code>false</code> if only single selection is allowed. * @param acceptFolders * <code>true</code> if folders can be selected in the * dialog. <code>false</code> only files and be selected. */ public FileSelectionValidator(boolean multiSelect, boolean acceptFolders) { this.m_multiSelect = multiSelect; this.m_acceptFolders = acceptFolders; } /** * * {@inheritDoc} */ public IStatus validate(Object[] selection) { int nSelected = selection.length; String pluginId = IDEWorkbenchPlugin.IDE_WORKBENCH; if (nSelected == 0 || (nSelected > 1 && !m_multiSelect)) { return new Status(IStatus.ERROR, pluginId, IStatus.ERROR, IDEResourceInfoUtils.EMPTY_STRING, null); } for (int i = 0; i < selection.length; i++) { Object curr = selection[i]; if (curr instanceof IFileStore) { IFileStore file = (IFileStore) curr; if (!m_acceptFolders && file.fetchInfo().isDirectory()) { return new Status(IStatus.ERROR, pluginId, IStatus.ERROR, IDEResourceInfoUtils.EMPTY_STRING, null); } } } return Status.OK_STATUS; } } /** gui element for remote filesystem roots */ private ListViewer m_fsRootBrowser; /** temporary storage for the model input for the fsRootBrowser */ private List<String> m_fsRootsInput; /** * Creates a new instance of the receiver. * * @param parent parent shell or null if none * @param multiSelect * <code>true</code> if multi selection is allowed. * <code>false</code> if only single selection is allowed. * @param type * one or both of <code>IResource.FILE</code> and * <code>IResource.FOLDER</code>, ORed together. If * <code>IResource.FILE</code> is specified files and folders * are displayed in the dialog. Otherwise only folders are * displayed. If <code>IResource.FOLDER</code> is specified * folders can be selected in addition to files. */ @SuppressWarnings("synthetic-access") public RemoteFileBrowserDialog(Shell parent, boolean multiSelect, int type) { super(parent, new FileLabelProvider(), new FileContentProvider( (type & IResource.FILE) != 0)); setShellStyle(getShellStyle() | SWT.APPLICATION_MODAL); setComparator(new FileViewerSorter()); setValidator(new FileSelectionValidator(multiSelect, (type & IResource.FOLDER) != 0)); setEmptyListMessage(Messages.AUTConfigComponentRemoteDirEmpty); } /** * {@inheritDoc} */ protected TreeViewer doCreateTreeViewer(Composite parent, int style) { m_fsRootBrowser = createFSRootSelector(parent, style); TreeViewer tv = super.doCreateTreeViewer(parent, style); return tv; } /** * @param parent Widget parent * @param style Widget style * @return a TableViewer for showing remote filesystem root elements. */ private ListViewer createFSRootSelector(Composite parent, int style) { ListViewer lv = new ListViewer(parent, style); lv.setContentProvider(new ArrayContentProvider()); lv.setInput(m_fsRootsInput); lv.addDoubleClickListener(new IDoubleClickListener() { @SuppressWarnings("synthetic-access") public void doubleClick(DoubleClickEvent event) { RemoteFileStore oldFS = (RemoteFileStore)getTreeViewer() .getInput(); final RemoteFileStore newRemoteFS = new RemoteFileStore(oldFS .getCommunicator(), (String)((StructuredSelection)(event.getSelection())) .getFirstElement(), true); setInput(newRemoteFS); getTreeViewer().setInput(newRemoteFS); getTreeViewer().getTree().setFocus(); } }); GridData data = new GridData(GridData.FILL_BOTH); org.eclipse.swt.widgets.List list = lv.getList(); list.setLayoutData(data); list.setFont(parent.getFont()); return lv; } /** * @param remoteFSRoots data for filesystem roots */ public void setFSRoots(List<String> remoteFSRoots) { m_fsRootsInput = remoteFSRoots; } /** * {@inheritDoc} */ public void setInput(Object input) { super.setInput(input); } /** * {@inheritDoc} */ public void create() { super.create(); selectRoot(); getTreeViewer().getTree().setFocus(); } /** * if allowed by the current creation state select a root entry */ private void selectRoot() { final TreeViewer treeViewer = getTreeViewer(); if (treeViewer != null) { final Object input = treeViewer.getInput(); if (input != null && input instanceof RemoteFileStore) { RemoteFileStore fs = (RemoteFileStore)input; if (m_fsRootBrowser != null) { m_fsRootBrowser.setSelection(new StructuredSelection(fs .getPath())); } } } } }