blob: e461296af52dcdb0e0b9a1a4fe2c6d7bf75abe32 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2015 Wind River Systems, Inc. and others. 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.tcf.filesystem.ui.dialogs;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.runtime.IFSTreeNode;
import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.runtime.IRuntimeModel;
import org.eclipse.tcf.te.tcf.filesystem.core.model.ModelManager;
import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin;
import org.eclipse.tcf.te.tcf.filesystem.ui.controls.FSTreeContentProvider;
import org.eclipse.tcf.te.tcf.filesystem.ui.controls.FSTreeViewerSorter;
import org.eclipse.tcf.te.tcf.filesystem.ui.interfaces.IFSConstants;
import org.eclipse.tcf.te.tcf.filesystem.ui.internal.columns.FSTreeElementLabelProvider;
import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode;
import org.eclipse.tcf.te.ui.trees.FilterDescriptor;
import org.eclipse.tcf.te.ui.trees.Pending;
import org.eclipse.tcf.te.ui.trees.ViewerStateManager;
import org.eclipse.ui.IDecoratorManager;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
/**
* File system open file dialog.
*/
public class FSOpenFileDialog extends ElementTreeSelectionDialog {
private String filterPath = null;
/* default */ TreeViewer viewer = null;
/**
* Create an FSFolderSelectionDialog using the specified shell as the parent.
*
* @param parentShell The parent shell.
*/
public FSOpenFileDialog(Shell parentShell) {
this(parentShell, new FSTreeElementLabelProvider(), new FSTreeContentProvider());
}
/**
* Create an FSFolderSelectionDialog using the specified shell, an FSTreeLabelProvider, and a
* content provider that provides the tree nodes.
*
* @param parentShell The parent shell.
* @param labelProvider The label provider.
* @param contentProvider The content provider.
*/
private FSOpenFileDialog(Shell parentShell, ILabelProvider labelProvider, ITreeContentProvider contentProvider) {
super(parentShell, createDecoratingLabelProvider(labelProvider), contentProvider);
setTitle(Messages.FSOpenFileDialog_title);
setMessage(Messages.FSOpenFileDialog_message);
this.setAllowMultiple(false);
this.setStatusLineAboveButtons(false);
this.setComparator(new FSTreeViewerSorter());
this.setValidator(new ISelectionStatusValidator() {
@Override
public IStatus validate(Object[] selection) {
return isValidSelection(selection);
}
});
}
/**
* Sets the filter path.
*
* @param filterPath The filter path or <code>null</code>.
*/
public void setFilterPath(String filterPath) {
this.filterPath = filterPath;
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.dialogs.ElementTreeSelectionDialog#setInput(java.lang.Object)
*/
@Override
public void setInput(Object input) {
super.setInput(input);
FilterDescriptor[] filterDescriptors = ViewerStateManager.getInstance().getFilterDescriptors(IFSConstants.ID_TREE_VIEWER_FS, input);
Assert.isNotNull(filterDescriptors);
for (FilterDescriptor descriptor : filterDescriptors) {
if (descriptor.isEnabled()) {
addFilter(descriptor.getFilter());
}
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.dialogs.ElementTreeSelectionDialog#create()
*/
@Override
public void create() {
super.create();
if (filterPath != null && !"".equals(filterPath.trim())) { //$NON-NLS-1$
IPath path = new Path(filterPath);
if (viewer.getInput() instanceof IPeerNode) {
Object element = null;
IRuntimeModel model = ModelManager.getRuntimeModel((IPeerNode)viewer.getInput());
if (model != null) {
IFSTreeNode root = model.getRoot();
ITreeContentProvider contentProvider = (ITreeContentProvider)viewer.getContentProvider();
Object[] elements = contentProvider.getElements(root);
String segment = path.getDevice() != null ? path.getDevice() : path.segmentCount() > 0 ? path.segment(0) : null;
if (segment != null) {
for (Object elem : elements) {
if (!(elem instanceof IFSTreeNode)) break;
IFSTreeNode child = (IFSTreeNode)elem;
String name = child.getName();
if (name.endsWith("\\") || name.endsWith("/")) name = name.substring(0, name.length() - 1); //$NON-NLS-1$ //$NON-NLS-2$
boolean matches = child.isWindowsNode() ? name.equalsIgnoreCase(segment) : name.equals(segment);
if (matches) {
if (path.segmentCount() > (path.getDevice() != null ? 0 : 1)) {
// Have to drill down a bit further
element = findRecursive(child, path, path.getDevice() != null ? 0 : 1);
if (element != null) break;
} else {
element = child;
break;
}
}
}
}
}
if (element != null) {
final ISelection selection = new StructuredSelection(element);
final AtomicInteger counter = new AtomicInteger();
Runnable runnable = new Runnable() {
@Override
public void run() {
viewer.setSelection(selection, true);
if (!selection.equals(viewer.getSelection())) {
if (counter.incrementAndGet() <= 10) {
viewer.getControl().getDisplay().asyncExec(this);
}
}
}
};
viewer.getControl().getDisplay().asyncExec(runnable);
}
}
}
}
/**
* Finds the given path within the file system hierarchy.
*
* @param parent The parent file system node. Must not be <code>null</code>.
* @param path The path. Must not be <code>null</code>.
* @param index The segment index.
*
* @return The matching file system node or <code>null</code>.
*/
private IFSTreeNode findRecursive(IFSTreeNode parent, IPath path, int index) {
Assert.isNotNull(parent);
Assert.isNotNull(path);
IFSTreeNode node = null;
ITreeContentProvider contentProvider = (ITreeContentProvider)viewer.getContentProvider();
Object[] elements = contentProvider.getElements(parent);
while (elements.length == 1 && elements[0] instanceof Pending) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
elements = contentProvider.getElements(parent);
}
String segment = path.segment(index);
for (Object element : elements) {
if (!(element instanceof IFSTreeNode)) break;
IFSTreeNode child = (IFSTreeNode)element;
String name = child.getName();
if (name.endsWith("\\") || name.endsWith("/")) name = name.substring(0, name.length() - 1); //$NON-NLS-1$ //$NON-NLS-2$
boolean matches = child.isWindowsNode() ? name.equalsIgnoreCase(segment) : name.equals(segment);
if (matches) {
if (path.segmentCount() > index + 1) {
// Have to drill down a bit further
node = findRecursive(child, path, index + 1);
if (node != null) break;
} else {
node = child;
break;
}
}
}
return node;
}
/**
* Create a decorating label provider using the specified label provider.
*
* @param labelProvider The label provider that actually provides labels and images.
* @return The decorating label provider.
*/
private static ILabelProvider createDecoratingLabelProvider(ILabelProvider labelProvider) {
IWorkbench workbench = PlatformUI.getWorkbench();
IDecoratorManager manager = workbench.getDecoratorManager();
ILabelDecorator decorator = manager.getLabelDecorator();
return new DecoratingLabelProvider(labelProvider,decorator);
}
/**
* Create the tree viewer and set it to the label provider.
*/
@Override
protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
viewer = super.doCreateTreeViewer(parent, style);
viewer.getTree().setLinesVisible(false);
return viewer;
}
/**
* If the specified selection is a valid folder to be selected.
*
* @param selection The selected folders.
* @return An error status if it is invalid or an OK status indicating it is valid.
*/
IStatus isValidSelection(Object[] selection) {
String pluginId = UIPlugin.getUniqueIdentifier();
IStatus error = new Status(IStatus.ERROR, pluginId, null);
if (selection == null || selection.length == 0) {
return error;
}
if (!(selection[0] instanceof IFSTreeNode)) {
return error;
}
IFSTreeNode target = (IFSTreeNode) selection[0];
if(!target.isFile()) {
return error;
}
return new Status(IStatus.OK, pluginId, null);
}
}