| /******************************************************************************* |
| * 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.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.action.IMenuListener; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.MenuManager; |
| 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.IStructuredSelection; |
| import org.eclipse.jface.viewers.ITreeContentProvider; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.jface.viewers.ViewerFilter; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.KeyAdapter; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Menu; |
| 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.ImageConsts; |
| import org.eclipse.tcf.te.tcf.filesystem.ui.internal.columns.FSTreeElementLabelProvider; |
| import org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers.MoveFilesHandler; |
| 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.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; |
| |
| /** |
| * <p> |
| * The folder selection dialog for a remote file system. To populate the tree of the selection |
| * dialog with the file system, you should call <code> |
| * ElementTreeSelectionDialog.setInput</code> to specify the peer model of the remote target. In |
| * order to validate the destination folder, you should also specify the nodes to be moved. The file |
| * selection dialog is of single selection. You can get the selected result by calling |
| * <code>getFirstResult</code>. The type of selected folder is an instance of IFSTreeNode. |
| * </p> |
| * <p> |
| * The following is a snippet of example code: |
| * |
| * <pre> |
| * FSFolderSelectionDialog dialog = new FSFolderSelectionDialog(shell); |
| * dialog.setInput(peer); |
| * dialog.setMovedNodes(nodes); |
| * if (dialog.open() == Window.OK) { |
| * Object obj = dialog.getFirstResult(); |
| * Assert.isTrue(obj instanceof IFSTreeNode); |
| * IFSTreeNode folder = (IFSTreeNode) obj; |
| * // Use folder ... |
| * } |
| * </pre> |
| * |
| * @see MoveFilesHandler |
| */ |
| public final class FSFolderSelectionDialog extends ElementTreeSelectionDialog { |
| // The nodes that are being moved. |
| private List<IFSTreeNode> movedNodes; |
| private final int mode; |
| |
| public static final int MODE_ALL = 0; |
| public static final int MODE_ALL_WARNING_NOT_WRITABLE = 1; |
| public static final int MODE_ONLY_WRITABLE = 2; |
| |
| /** |
| * Create an FSFolderSelectionDialog using the specified shell as the parent. |
| * |
| * @param parentShell The parent shell. |
| */ |
| public FSFolderSelectionDialog(Shell parentShell) { |
| this(parentShell, MODE_ONLY_WRITABLE); |
| } |
| |
| /** |
| * Create an FSFolderSelectionDialog using the specified shell as the parent. |
| * |
| * @param parentShell The parent shell. |
| * @param mode The mode of this dialog. |
| */ |
| public FSFolderSelectionDialog(Shell parentShell, int mode) { |
| this(parentShell, new FSTreeElementLabelProvider(), new FSTreeContentProvider(), mode); |
| } |
| |
| /** |
| * 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. |
| * @param mode The mode of this dialog. |
| */ |
| private FSFolderSelectionDialog(Shell parentShell, ILabelProvider labelProvider, ITreeContentProvider contentProvider, int mode) { |
| super(parentShell, createDecoratingLabelProvider(labelProvider), contentProvider); |
| this.mode = mode; |
| setTitle(Messages.FSFolderSelectionDialog_MoveDialogTitle); |
| setMessage(Messages.FSFolderSelectionDialog_MoveDialogMessage); |
| this.setAllowMultiple(false); |
| this.setComparator(new FSTreeViewerSorter()); |
| this.addFilter(new DirectoryFilter()); |
| this.setStatusLineAboveButtons(true); |
| this.setValidator(new ISelectionStatusValidator() { |
| @Override |
| public IStatus validate(final Object[] selection) { |
| return isValidFolder(selection); |
| } |
| }); |
| } |
| |
| /** |
| * The viewer filter used to filter out files. |
| */ |
| static class DirectoryFilter extends ViewerFilter { |
| @Override |
| public boolean select(Viewer viewer, Object parentElement, Object element) { |
| if (element instanceof IFSTreeNode) { |
| IFSTreeNode node = (IFSTreeNode) element; |
| if(node.isFile()) return false; |
| } |
| return true; |
| } |
| } |
| |
| /* |
| * (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()); |
| } |
| } |
| } |
| |
| /** |
| * 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); |
| } |
| |
| /** |
| * Set the nodes that are about to be moved. |
| * |
| * @param movedNodes The nodes. |
| */ |
| public void setMovedNodes(List<IFSTreeNode> movedNodes) { |
| this.movedNodes = movedNodes; |
| } |
| |
| @Override |
| public TreeViewer getTreeViewer() { |
| return super.getTreeViewer(); |
| } |
| |
| /** |
| * Create the tree viewer and set it to the label provider. |
| */ |
| @Override |
| protected TreeViewer doCreateTreeViewer(Composite parent, int style) { |
| TreeViewer viewer = super.doCreateTreeViewer(parent, style); |
| |
| Button refreshAll = new Button(parent, SWT.PUSH); |
| refreshAll.setText(Messages.FSFolderSelectionDialog_RefreshAll_menu); |
| refreshAll.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| refreshModel(); |
| } |
| }); |
| |
| viewer.getTree().addKeyListener(new KeyAdapter() { |
| /* (non-Javadoc) |
| * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent) |
| */ |
| @Override |
| public void keyReleased(KeyEvent e) { |
| if (e.keyCode == SWT.F5) { |
| refresh(); |
| } |
| } |
| }); |
| viewer.getTree().setLinesVisible(false); |
| |
| MenuManager menuMgr = new MenuManager(); |
| menuMgr.setRemoveAllWhenShown(true); |
| menuMgr.addMenuListener(new IMenuListener() { |
| @Override |
| public void menuAboutToShow(IMenuManager manager) { |
| IAction action = new Action(Messages.FSFolderSelectionDialog_Refresh_menu, UIPlugin.getImageDescriptor(ImageConsts.REFRESH_IMAGE)) { |
| @Override |
| public void run() { |
| refresh(); |
| } |
| }; |
| action.setAccelerator(SWT.F5); |
| manager.add(action); |
| } |
| }); |
| Menu menu = menuMgr.createContextMenu(viewer.getControl()); |
| viewer.getControl().setMenu(menu); |
| |
| return viewer; |
| } |
| |
| public void refresh() { |
| ISelection sel = getTreeViewer().getSelection(); |
| if (sel instanceof IStructuredSelection && !sel.isEmpty()) { |
| Iterator<Object> it = ((IStructuredSelection)sel).iterator(); |
| while (it.hasNext()) { |
| Object node = it.next(); |
| if (node instanceof IFSTreeNode) { |
| refreshNode((IFSTreeNode)node); |
| } |
| else { |
| refreshModel(); |
| return; |
| } |
| } |
| } |
| else { |
| refreshModel(); |
| } |
| } |
| |
| protected void refreshNode(final IFSTreeNode treeNode) { |
| treeNode.operationRefresh(true).runInJob(null); |
| } |
| |
| protected void refreshModel() { |
| Object input = getTreeViewer().getInput(); |
| if (input instanceof IPeerNode) { |
| IRuntimeModel rtm = ModelManager.getRuntimeModel((IPeerNode)input); |
| if (rtm != null) |
| refreshNode(rtm.getRoot()); |
| } |
| } |
| |
| |
| private final static IStatus error = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), null); |
| private final static IStatus errorNotWritable = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), Messages.FSFolderSelectionDialog_notWritable_error); |
| private final static IStatus warningNotWritable = new Status(IStatus.WARNING, UIPlugin.getUniqueIdentifier(), Messages.FSFolderSelectionDialog_notWritable_warning); |
| |
| /** |
| * 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 isValidFolder(Object[] selection) { |
| if (selection == null || selection.length == 0) { |
| return error; |
| } |
| if (!(selection[0] instanceof IFSTreeNode)) { |
| return error; |
| } |
| IFSTreeNode target = (IFSTreeNode) selection[0]; |
| if (movedNodes != null) { |
| for (IFSTreeNode node : movedNodes) { |
| if (node == target || node.isAncestorOf(target)) { |
| return error; |
| } |
| } |
| } |
| if(mode != MODE_ALL && !target.isWritable()) { |
| return mode == MODE_ONLY_WRITABLE ? errorNotWritable : warningNotWritable; |
| } |
| return Status.OK_STATUS; |
| } |
| } |