blob: fecd2e4662577ebf40382b4dfe380ec5d6bead68 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 Borland Software Corporation and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Borland Software Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.emf.util.ui.controls;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
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.CellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.m2m.internal.qvt.oml.emf.util.Logger;
import org.eclipse.m2m.internal.qvt.oml.emf.util.StatusUtil;
import org.eclipse.m2m.internal.qvt.oml.emf.util.WorkspaceUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
public class SelectFileControl extends Composite {
public static interface IFilter {
boolean accept(IResource resource);
}
public static interface ISelectionListener {
void selectionChanged(IPath selectedPath);
}
public SelectFileControl(Composite parentComposite, boolean onlyExisting, IFilter resourceFilter) {
this(parentComposite, DEFAULT_FNAME, DEFAULT_FNAME, onlyExisting, resourceFilter);
}
public SelectFileControl(Composite parentComposite, String fileName, String defaultFileName, boolean onlyExisting, IFilter resourceFilter) {
super(parentComposite,SWT.NULL);
myResourceFilter = resourceFilter;
mySelectionListeners = new ArrayList<ISelectionListener>();
myOnlyExisting = onlyExisting;
myDefaultFileName = defaultFileName == null ? DEFAULT_FNAME : defaultFileName;
myFileName = fileName == null ? myDefaultFileName : fileName;
myCreatedFiles = new HashSet<IFile>();
IResource root = ResourcesPlugin.getWorkspace().getRoot();
setLayout(new GridLayout());
myViewer = new TreeViewer(this, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
Label secondLabel = new Label(this, SWT.LEFT);
secondLabel.setText(Messages.SelectFileControl_SelectedFile);
myFileNameText = new Text(this, SWT.BORDER);
myFileNameText.setEnabled(!myOnlyExisting);
myFileNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
myFileNameText.setText(myFileName);
myFileNameText.addModifyListener(FNAME_LISTENER);
myViewer.setContentProvider(CONTENT_PROVIDER);
myViewer.setLabelProvider(new WorkbenchLabelProvider());
myViewer.setAutoExpandLevel(DEFAUL_AUTO_EXPAND_LEVEL);
myViewer.addFilter(VIEWER_FILTER);
myViewer.setSorter(VIEWER_SORTER);
myViewer.addSelectionChangedListener(VIEWER_LISTENER);
myViewer.setColumnProperties(new String[] {NAME_COLUMN});
Tree tree = (Tree) myViewer.getControl();
myViewer.setCellEditors(new CellEditor[] {
new TextCellEditor(tree, SWT.BORDER | SWT.SINGLE),
});
myViewer.setCellModifier(FILE_CELL_MODIFIER);
GridData data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
data.grabExcessVerticalSpace = true;
data.heightHint = 250;
data.widthHint = 350;
myViewer.getControl().setLayoutData(data);
myViewer.setInput(root);
hookContextMenu();
}
void addCreatedFile(IFile file) {
myCreatedFiles.add(file);
}
void removeCreatedFile(IFile file) {
myCreatedFiles.remove(file);
}
private void hookContextMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
SelectFileControl.this.fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(myViewer.getControl());
myViewer.getControl().setMenu(menu);
}
protected void fillContextMenu(IMenuManager manager) {
if(!myOnlyExisting) {
addNewFileAction(manager);
}
}
private void addNewFileAction(IMenuManager manager) {
ISelection selection = myViewer.getSelection();
if(selection == null || selection.isEmpty()) {
return;
}
if(selection instanceof IStructuredSelection == false) {
return;
}
IStructuredSelection structuredSelection = (IStructuredSelection) selection;
Object obj = structuredSelection.iterator().next();
if(obj instanceof IContainer == false) {
return;
}
IContainer cont = (IContainer)obj;
IAction newFileAction = new NewFileAction(this, cont, myDefaultFileName);
newFileAction.setText(Messages.SelectFileControl_NewFile);
newFileAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().
getImageDescriptor(ISharedImages.IMG_OBJ_FILE));
manager.add(newFileAction);
}
public void addSelectionListener(ISelectionListener listener) {
mySelectionListeners.add(listener);
}
public void removeSelectionListener(ISelectionListener listener) {
mySelectionListeners.remove(listener);
}
public void setSelection(ISelection selection) {
myViewer.setSelection(selection);
}
private void fileSelectionChanged(IPath selectedPath) {
for (Iterator<ISelectionListener> it = new ArrayList<ISelectionListener>(mySelectionListeners).iterator(); it.hasNext();) {
ISelectionListener listener = it.next();
try {
listener.selectionChanged(selectedPath);
}
catch(Exception e) {
}
}
}
public TreeViewer getViewer(){
return myViewer;
}
public IPath getSelectedPath() {
return myPath;
}
public IFile getSelectedFile() {
return myPath == null ? null : WorkspaceUtils.getWorkspaceFile(myPath.toString());
}
private final ViewerFilter VIEWER_FILTER = new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof IResource == false) {
return false;
}
if(element instanceof IContainer) {
IContainer container = (IContainer)element;
if(!myOnlyExisting) {
return true;
}
boolean has = hasMatchingChildrenRecursive(container, myResourceFilter);
return has;
}
else {
return resourceMatches(myResourceFilter, (IResource)element);
}
}
private boolean hasMatchingChildrenRecursive(IContainer container, final IFilter filter) {
try {
IResource[] members = container.members();
for (IResource member : members) {
if (resourceMatches(filter, member)) {
return true;
}
if(member instanceof IContainer) {
boolean has = hasMatchingChildrenRecursive((IContainer) member, filter);
if(has) {
return true;
}
}
}
}
catch (Exception e) {
}
return false;
}
private boolean resourceMatches(final IFilter filter, IResource member) {
return filter == null || filter.accept(member);
}
};
public void selectFileByPath(String path) {
IFile file = WorkspaceUtils.getWorkspaceFile(path);
if (file != null) {
StructuredSelection sel = new StructuredSelection(new Object[] {file});
myViewer.setSelection(sel);
}
}
private static final ViewerSorter VIEWER_SORTER = new ViewerSorter() {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
boolean folderLeft = (e1 instanceof IContainer);
boolean folderRight = (e2 instanceof IContainer);
if (folderLeft == folderRight) {
return super.compare(viewer, e1, e2);
}
return folderLeft ? -1 : 1;
}
};
private final ISelectionChangedListener VIEWER_LISTENER = new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection)event.getSelection();
try {
myFileNameText.removeModifyListener(FNAME_LISTENER);
IResource resource;
if(selection == null) {
resource = null;
myFileNameText.setText("");//$NON-NLS-1$
}
else {
resource = (IResource)selection.getFirstElement();
if(resource instanceof IFile) {
myFileNameText.setText(resource.getName());
myFileNameText.setEnabled(false);
}
else {
if(myOnlyExisting) {
myFileNameText.setText(""); //$NON-NLS-1$
myFileNameText.setEnabled(false);
}
else {
myFileNameText.setEnabled(true);
IPath computePath = IPathUtils.computePath(myResource, myFileNameText.getText());
if (computePath != null && myDefaultFileName != null) {
IFile file = WorkspaceUtils.getWorkspaceFile(computePath.toString());
if (file != null && file.exists()) {
myFileNameText.setText(myDefaultFileName);
}
}
}
}
}
myResource = resource;
myPath = IPathUtils.computePath(myResource, myFileNameText.getText());
fileSelectionChanged(myPath);
}
finally {
myFileNameText.addModifyListener(FNAME_LISTENER);
}
}
};
private final ModifyListener FNAME_LISTENER = new ModifyListener() {
public void modifyText(ModifyEvent e) {
myFileName = myFileNameText.getText();
myPath = IPathUtils.computePath(myResource, myFileName);
fileSelectionChanged(myPath);
}
};
private final boolean myOnlyExisting;
private TreeViewer myViewer;
private Text myFileNameText;
private String myFileName;
private String myDefaultFileName;
private final IFilter myResourceFilter;
private IResource myResource;
private IPath myPath;
private final Set<IFile> myCreatedFiles;
private final List<ISelectionListener> mySelectionListeners;
private static final int DEFAUL_AUTO_EXPAND_LEVEL = 0;
private static final String NAME_COLUMN = "name"; //$NON-NLS-1$
private static final String DEFAULT_FNAME = "New File"; //$NON-NLS-1$
private final ICellModifier FILE_CELL_MODIFIER = new ICellModifier() {
public boolean canModify(Object element, String property) {
return element instanceof IFile && myCreatedFiles.contains(element);
}
public Object getValue(Object element, String property) {
if(element instanceof IFile == false || !NAME_COLUMN.equals(property)) {
return null;
}
return ((IFile)element).getName();
}
public void modify(Object element, String property, Object value) {
if (element instanceof TreeItem == false || !NAME_COLUMN.equals(property)) {
return;
}
Object data = ((TreeItem)element).getData();
if(data instanceof IFile == false ) {
return;
}
IFile file = (IFile)data;
String newName = (String)value;
if(newName == null || newName.length() == 0) {
return;
}
if(file.getName().equals(newName)) {
return;
}
IStatus status = file.getProject().getWorkspace().validateName(newName, IResource.FILE);
if(StatusUtil.isError(status)) {
Logger.getLogger().log(Logger.WARNING, "Validation failed for " + newName + ": " + status.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
IPath newPath = new Path(newName);
IFile newFile;
try {
newFile = file.getParent().getFile(newPath);
}
catch(Exception e) {
Logger.getLogger().log(Logger.WARNING, "Failed to get file " + newPath + "parent= " + file.getParent(), e); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
if(!newFile.getParent().equals(file.getParent())) {
return;
}
if(newFile.exists()) {
return;
}
removeCreatedFile(file);
addCreatedFile(newFile);
myViewer.refresh();
myViewer.setSelection(new StructuredSelection(newFile));
}
};
private ITreeContentProvider CONTENT_PROVIDER = new ITreeContentProvider() {
ITreeContentProvider myProvider = new WorkbenchContentProvider();
public Object[] getChildren(Object parentElement) {
Object[] children = myProvider.getChildren(parentElement);
if(myOnlyExisting) {
return children;
}
if(parentElement instanceof IContainer == false) {
return children;
}
List<Object> allChildren = new ArrayList<Object>();
if(children != null) {
allChildren.addAll(Arrays.asList(children));
}
IContainer container = (IContainer)parentElement;
allChildren.addAll(getCreatedChildren(container));
return allChildren.toArray();
}
private List<Object> getCreatedChildren(IContainer container) {
List<Object> children = new ArrayList<Object>();
for(IFile file : myCreatedFiles) {
if(container.equals(file.getParent())) {
children.add(file);
}
}
return children;
}
public Object getParent(Object element) {
Object parent = myProvider.getParent(element);
if(parent != null) {
return parent;
}
if(element instanceof IFile == false) {
return null;
}
IFile file = (IFile) element;
return file.getParent();
}
public boolean hasChildren(Object element) {
if(myProvider.hasChildren(element)) {
return true;
}
if(element instanceof IContainer == false) {
return false;
}
return !getCreatedChildren((IContainer) element).isEmpty();
}
public Object[] getElements(Object inputElement) {
return myProvider.getElements(inputElement);
}
public void dispose() {
myProvider.dispose();
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
myProvider.inputChanged(viewer, oldInput, newInput);
}
};
}