blob: e86029ab82d43cfe8ec74e415e08c0371299e252 [file] [log] [blame]
// Copyright (c) 2010 The Chromium Authors. 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
package org.eclipse.wst.jsdt.chromium.debug.ui.actions;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.viewers.IStructuredSelection;
/**
* A utility class for creating actions that work with files in selection.
* User should extend either {@link Single} or {@link Multiple} nested class.
* Custom file filter is supported.
*/
class FileBasedAction {
/**
* A base class for actions that are enabled for a single file. User provides
* a {@link FileFilter} that may additionally convert low-level {@link IFile}
* to a user type RES.
* @param <RES> a user-specified type that corresponds to a file
*/
static abstract class Single<RES> extends SelectionBasedAction.Single<RES> {
private final FileFilter<RES> fileFilter;
/**
* @param allowMutipleSelection see javadoc for {@link SelectionBasedAction.Single}
*/
protected Single(boolean allowMutipleSelection, FileFilter<RES> fileFilter) {
super(allowMutipleSelection);
this.fileFilter = fileFilter;
}
@Override
protected RES castElement(Object element) {
List<RES> files = readFilesFromSelectionObject(element, fileFilter);
if (files.size() != 1) {
return null;
}
return files.get(0);
}
}
/**
* A base class for actions that are enabled for several files. User provides
* a {@link FileFilter} that may additionally convert low-level {@link IFile}
* to a user type RES.
* @param <RES> a user-specified type that corresponds to a file
*/
static abstract class Multiple<RES> extends SelectionBasedAction.Multiple<RES> {
private final FileFilter<RES> fileFilter;
protected Multiple(FileFilter<RES> fileFilter) {
this.fileFilter = fileFilter;
}
@Override
protected List<? extends RES> readSelection(
IStructuredSelection selection) {
List<RES> files = new ArrayList<RES>(1);
for (Iterator<?> it = selection.iterator(); it.hasNext(); ) {
Object element = it.next();
files.addAll(readFilesFromSelectionObject(element, fileFilter));
}
return files;
}
}
/**
* A filter that converts input file into a user type T or null.
* @param <T>
*/
static abstract class FileFilter<T> {
/**
* @return user data or null if the file should be ignored
*/
abstract T accept(IFile file);
}
private static <RES> List<RES> readFilesFromSelectionObject(Object element,
FileFilter<RES> fileFilter) {
if (element instanceof ResourceMapping == false) {
return null;
}
ResourceMapping resourceMapping = (ResourceMapping) element;
return readFiles(resourceMapping, fileFilter);
}
private static <RES> List<RES> readFiles(ResourceMapping resourceMapping,
final FileFilter<RES> fileFilter) {
final List<RES> fileList = new ArrayList<RES>(1);
IResourceVisitor visitor = new IResourceVisitor() {
public boolean visit(IResource resource) throws CoreException {
if (resource instanceof IFile == false) {
return true;
} else {
IFile file = (IFile) resource;
RES res = fileFilter.accept(file);
if (res != null) {
fileList.add(res);
}
return false;
}
}
};
try {
// This will always return one project
IProject project = resourceMapping.getProjects()[0];
if(project.isOpen())
resourceMapping.accept(null, visitor, null);
} catch (CoreException e) {
throw new RuntimeException(e);
}
return fileList;
}
}