blob: fdd83ac9fc7f9234aa88d2e58ad334a6a0a45850 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2014 IBM Corporation 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:
* Serge Beauchamp (Freescale Semiconductor) - initial API and implementation
* Lars Vogel <Lars.Vogel@gmail.com> - Bug 430694
******************************************************************************/
package org.eclipse.ui.internal.ide.dialogs;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TreeMap;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.model.WorkbenchLabelProvider;
/**
* UI to edit the location of the linked resources contained in a project.
* @since 3.5
*
*/
public class LinkedResourceEditor {
private static int NAME_COLUMN = 0;
private static int PATH_COLUMN = -1;
private static int LOCATION_COLUMN = 1;
// sizing constants
private static final int SIZING_SELECTION_PANE_WIDTH = 400;
// used to compute layout sizes
private FontMetrics fontMetrics;
/**
*
*/
public LinkedResourceEditor() {
absoluteImg = IDEWorkbenchPlugin.getIDEImageDescriptor(
"obj16/warning.png").createImage(); //$NON-NLS-1$
brokenImg = IDEWorkbenchPlugin.getIDEImageDescriptor(
"obj16/error_tsk.png").createImage(); //$NON-NLS-1$
fixedImg = IDEWorkbenchPlugin
.getIDEImageDescriptor("obj16/folder.png").createImage(); //$NON-NLS-1$
FIXED = IDEWorkbenchMessages.LinkedResourceEditor_fixed;
BROKEN = IDEWorkbenchMessages.LinkedResourceEditor_broken;
ABSOLUTE = IDEWorkbenchMessages.LinkedResourceEditor_absolute;
}
/**
* @param project
*/
public void setProject(IProject project) {
fProject = project;
}
protected void createButtons(Composite parent) {
Font font = parent.getFont();
Composite groupComponent = new Composite(parent, SWT.NULL);
GridLayout groupLayout = new GridLayout();
groupLayout.marginWidth = 0;
groupLayout.marginHeight = 0;
groupComponent.setLayout(groupLayout);
GridData data = new GridData();
data.verticalAlignment = GridData.FILL;
data.horizontalAlignment = GridData.FILL;
groupComponent.setLayoutData(data);
groupComponent.setFont(font);
fEditResourceButton = createButton(groupComponent,
IDEWorkbenchMessages.LinkedResourceEditor_editLinkedLocation);
fEditResourceButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
editLocation();
}
});
fConvertAbsoluteButton = createButton(groupComponent,
IDEWorkbenchMessages.LinkedResourceEditor_convertToVariableLocation);
fConvertAbsoluteButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
convertLocation();
}
});
fRemoveButton = createButton(groupComponent,
IDEWorkbenchMessages.LinkedResourceEditor_remove);
fRemoveButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
removeSelection();
}
});
updateSelection();
}
/**
* @param parent
* @param text
* @return the new button
*/
private Button createButton(Composite parent, String text) {
Button button = new Button(parent, SWT.PUSH);
button.setText(text);
button.setFont(parent.getFont());
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
int widthHint = Dialog.convertHorizontalDLUsToPixels(fontMetrics,
IDialogConstants.BUTTON_WIDTH);
data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT,
SWT.DEFAULT, true).x);
button.setLayoutData(data);
return button;
}
/**
* Creates the widget group. Callers must call <code>dispose</code> when the
* group is no longer needed.
*
* @param parent
* the widget parent
* @return container of the widgets
*/
public Control createContents(Composite parent) {
Font font = parent.getFont();
initializeDialogUnits(parent);
// define container & its layout
Composite pageComponent = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginWidth = 0;
layout.marginHeight = 0;
pageComponent.setLayout(layout);
GridData data = new GridData(GridData.FILL_BOTH);
data.widthHint = SIZING_SELECTION_PANE_WIDTH;
pageComponent.setLayoutData(data);
pageComponent.setFont(font);
// layout the table & its buttons
Label variableLabel = new Label(pageComponent, SWT.LEFT);
variableLabel.setText(NLS
.bind(IDEWorkbenchMessages.LinkedResourceEditor_descriptionBlock,
fProject != null? fProject.getName():new String()));
data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.horizontalSpan = 2;
variableLabel.setLayoutData(data);
variableLabel.setFont(font);
Composite treeComposite = new Composite(pageComponent, SWT.NONE);
data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.grabExcessHorizontalSpace = true;
data.grabExcessVerticalSpace = true;
treeComposite.setLayoutData(data);
fTree = new TreeViewer(treeComposite, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
fTree.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
updateSelection();
}
});
data = new GridData(GridData.FILL_BOTH);
data.heightHint = fTree.getTree().getItemHeight() * 10;
data.horizontalSpan = 1;
fTree.getTree().setLayoutData(data);
fTree.getTree().setLinesVisible(true);
fTree.setContentProvider(new ContentProvider());
fTree.setLabelProvider(new LabelProvider());
fTree.setInput(this);
TreeColumn nameColumn = new TreeColumn(fTree.getTree(), SWT.LEFT, NAME_COLUMN);
nameColumn.setText(IDEWorkbenchMessages.LinkedResourceEditor_resourceName);
nameColumn.setResizable(true);
nameColumn.setMoveable(false);
TreeColumn locationColumn = new TreeColumn(fTree.getTree(), SWT.LEFT, LOCATION_COLUMN);
locationColumn.setText(IDEWorkbenchMessages.LinkedResourceEditor_location);
locationColumn.setResizable(true);
locationColumn.setMoveable(false);
TreeColumnLayout tableLayout = new TreeColumnLayout();
treeComposite.setLayout( tableLayout );
tableLayout.setColumnData(nameColumn, new ColumnWeightData(170));
tableLayout.setColumnData(locationColumn, new ColumnWeightData(260));
fTree.getTree().setFont(font);
fTree.getTree().setHeaderVisible(true);
createButtons(pageComponent);
fTree.getTree().addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick(MouseEvent e) {
if (getSelectedResource().length == 1)
editLocation();
}
});
fTree.getTree().addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.keyCode == SWT.DEL) {
e.doit = false;
if (getSelectedResource().length > 0)
removeSelection();
}
}
});
return pageComponent;
}
private void initializeDialogUnits(Control control) {
// Compute and store a font metric
GC gc = new GC(control);
gc.setFont(control.getFont());
fontMetrics = gc.getFontMetrics();
gc.dispose();
}
/**
*
*/
public void dispose() {
fixedImg.dispose();
brokenImg.dispose();
absoluteImg.dispose();
}
class LabelProvider implements ILabelProvider,
ITableLabelProvider {
WorkbenchLabelProvider stockProvider = new WorkbenchLabelProvider();
public LabelProvider() {
super();
}
@Override
public String getColumnText(Object obj, int index) {
if (obj instanceof IResource) {
IResource resource = (IResource) obj;
if (index == NAME_COLUMN)
return resource.getName();
else if (index == PATH_COLUMN)
return resource.getParent()
.getProjectRelativePath().toPortableString();
else {
IPath rawLocation = resource.getRawLocation();
if (rawLocation != null)
return resource.getPathVariableManager().convertToUserEditableFormat(rawLocation.toOSString(), true);
}
} else if ((obj instanceof String) && index == 0)
return (String) obj;
return null;
}
@Override
public Image getColumnImage(Object obj, int index) {
if (index == NAME_COLUMN) {
if (obj instanceof String) {
if (obj.equals(BROKEN))
return brokenImg;
if (obj.equals(ABSOLUTE))
return absoluteImg;
return fixedImg;
}
return stockProvider.getImage(obj);
}
return null;
}
@Override
public void addListener(ILabelProviderListener listener) {
}
@Override
public void dispose() {
stockProvider.dispose();
}
@Override
public boolean isLabelProperty(Object element, String property) {
return stockProvider.isLabelProperty(element, property);
}
@Override
public void removeListener(ILabelProviderListener listener) {
}
@Override
public Image getImage(Object element) {
return getColumnImage(element, 0);
}
@Override
public String getText(Object element) {
return getColumnText(element, 0);
}
}
class ContentProvider implements IContentProvider, ITreeContentProvider {
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof LinkedResourceEditor) {
ArrayList list = new ArrayList();
Object[] objs = { BROKEN, ABSOLUTE, FIXED };
for (int i = 0; i < objs.length; i++) {
Object[] children = getChildren(objs[i]);
if (children != null && children.length > 0)
list.add(objs[i]);
}
return list.toArray(new Object[0]);
} else if (parentElement instanceof String) {
if (((String) parentElement).equals(BROKEN))
return fBrokenResources.values().toArray();
if (((String) parentElement).equals(ABSOLUTE))
return fAbsoluteResources.values().toArray();
return fFixedResources.values().toArray();
}
return null;
}
@Override
public Object getParent(Object element) {
if (element instanceof IResource) {
String fullPath = ((IResource) element).getFullPath()
.toPortableString();
if (fBrokenResources.containsKey(fullPath))
return BROKEN;
if (fAbsoluteResources.containsKey(fullPath))
return ABSOLUTE;
return FIXED;
} else if (element instanceof String)
return this;
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element instanceof LinkedResourceEditor) {
return true;
} else if (element instanceof String) {
if (((String) element).equals(BROKEN))
return !fBrokenResources.isEmpty();
if (((String) element).equals(ABSOLUTE))
return !fAbsoluteResources.isEmpty();
return !fFixedResources.isEmpty();
}
return false;
}
@Override
public Object[] getElements(Object parentElement) {
return getChildren(parentElement);
}
}
void refreshContent() {
IResource[] projectFiles;
if (!initialized) {
final LinkedList/* <IResource> */resources = new LinkedList/*
* <IResource
* >
*/();
try {
fProject.accept(new IResourceVisitor() {
/**
* @throws CoreException
*/
@Override
public boolean visit(IResource resource)
throws CoreException {
if (resource.isLinked() && !resource.isVirtual())
resources.add(resource);
return true;
}
});
} catch (CoreException e) {
}
projectFiles = (IResource[]) resources.toArray(new IResource[0]);
initialized = true;
}
else {
ArrayList/*<IResource>*/ list = new ArrayList();
list.addAll(fBrokenResources.values());
list.addAll(fFixedResources.values());
list.addAll(fAbsoluteResources.values());
projectFiles = (IResource[]) list.toArray(new IResource[0]);
}
fBrokenResources = new TreeMap/* <String, IResource> */();
fFixedResources = new TreeMap/* <String, IResource> */();
fAbsoluteResources = new TreeMap/* <String, IResource> */();
for (int i = 0; i < projectFiles.length; i++) {
IResource resource = projectFiles[i];
String fullPath = resource.getFullPath().toPortableString();
try {
if (exists(resource)) {
if (isAbsolute(resource))
fAbsoluteResources.put(fullPath, resource);
else
fFixedResources.put(fullPath, resource);
} else
fBrokenResources.put(fullPath, resource);
} catch (CoreException e) {
fBrokenResources.put(fullPath, resource);
}
}
}
boolean isAbsolute(IResource res) {
IPath path = res.getRawLocation();
return path != null && path.isAbsolute();
}
boolean areAbsolute(IResource[] res) {
for (int i = 0; i < res.length; i++) {
if (!isAbsolute(res[i]))
return false;
}
return true;
}
boolean exists(IResource res) throws CoreException {
URI uri = res.getLocationURI();
if (uri != null) {
IFileStore fileStore = EFS.getStore(uri);
return (fileStore != null) && fileStore.fetchInfo().exists();
}
return false;
}
void updateSelection() {
fEditResourceButton.setEnabled(getSelectedResource().length == 1);
fConvertAbsoluteButton.setEnabled((getSelectedResource().length > 0)
&& (areAbsolute(getSelectedResource())
|| areFixed(getSelectedResource())));
fRemoveButton.setEnabled(getSelectedResource().length > 0);
}
boolean areFixed(IResource[] res) {
for (int i = 0; i < res.length; i++) {
String fullPath = res[i].getFullPath().toPortableString();
if (!fFixedResources.containsKey(fullPath))
return false;
}
return true;
}
IResource[] getSelectedResource() {
IStructuredSelection selection = (IStructuredSelection) fTree
.getSelection();
Object[] array = selection.toArray();
if (array.length > 0) {
for (int i = 0; i < array.length; i++) {
if (!(array[i] instanceof IResource))
return new IResource[0];
}
IResource[] result = new IResource[array.length];
System.arraycopy(array, 0, result, 0, array.length);
return result;
}
return new IResource[0];
}
private void convertLocation() {
if (MessageDialog.openConfirm(fConvertAbsoluteButton.getShell(),
IDEWorkbenchMessages.LinkedResourceEditor_convertTitle,
IDEWorkbenchMessages.LinkedResourceEditor_convertMessage)) {
ArrayList/* <IResource> */resources = new ArrayList/* <IResource> */();
IResource[] selectedResources = getSelectedResource();
resources.addAll(Arrays.asList(selectedResources));
if (areFixed(selectedResources))
convertToAbsolute(resources, selectedResources);
else
convertToRelative(resources, selectedResources);
}
}
private void removeSelection() {
if (MessageDialog.openConfirm(fRemoveButton.getShell(),
IDEWorkbenchMessages.LinkedResourceEditor_removeTitle,
IDEWorkbenchMessages.LinkedResourceEditor_removeMessage)) {
final IResource[] selectedResources = getSelectedResource();
final ArrayList/*<IResource>*/ removedResources = new ArrayList();
IRunnableWithProgress op = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) {
try {
monitor.beginTask(
IDEWorkbenchMessages.LinkedResourceEditor_removingMessage,
selectedResources.length);
for (int i = 0; i < selectedResources.length; i++) {
if (monitor.isCanceled())
break;
String fullPath = selectedResources[i]
.getFullPath().toPortableString();
try {
selectedResources[i].delete(true, new SubProgressMonitor(monitor, 1));
removedResources.add(selectedResources[i]);
fBrokenResources.remove(fullPath);
fFixedResources.remove(fullPath);
fAbsoluteResources.remove(fullPath);
} catch (CoreException e) {
e.printStackTrace();
}
}
} finally {
monitor.done();
}
}
};
try {
new ProgressMonitorDialog(fRemoveButton.getShell()).run(true,
true, op);
} catch (InvocationTargetException e) {
IDEWorkbenchPlugin.log(null, e);
} catch (InterruptedException e) {
IDEWorkbenchPlugin.log(null, e);
}
fTree.refresh();
}
}
private void convertToAbsolute(ArrayList/* <IResource> */resources,
IResource[] selectedResources) {
ArrayList/* <String> */report = new ArrayList/* <String> */();
Iterator/* <IResource> */it = resources.iterator();
while (it.hasNext()) {
IResource res = (IResource) it.next();
IPath location = res.getLocation();
try {
setLinkLocation(res, location);
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_changedTo,
new Object[] {
res.getProjectRelativePath()
.toPortableString(),
res.getRawLocation()
.toOSString(),
location.toOSString() }));
} catch (CoreException e) {
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_unableToSetLinkLocationForResource,
res.getProjectRelativePath()
.toPortableString()));
}
}
reportResult(
selectedResources,
report,
IDEWorkbenchMessages.LinkedResourceEditor_convertRelativePathLocations);
}
/**
* @param res
* @param location
* @throws CoreException
*/
private void setLinkLocation(IResource res, IPath location) throws CoreException {
if (res.getType() == IResource.FILE)
((IFile)res).createLink(location, IResource.REPLACE,
new NullProgressMonitor());
if (res.getType() == IResource.FOLDER)
((IFolder)res).createLink(location, IResource.REPLACE,
new NullProgressMonitor());
}
/**
* @param selectedResources
* @param report
*/
private void reportResult(IResource[] selectedResources,
ArrayList/* <String> */report, String title) {
StringBuffer message = new StringBuffer();
Iterator/* <String> */stringIt = report.iterator();
while (stringIt.hasNext()) {
message.append(stringIt.next());
if (stringIt.hasNext())
message.append("\n"); //$NON-NLS-1$
}
final String resultMessage = message.toString();
MessageDialog dialog = new MessageDialog(fConvertAbsoluteButton
.getShell(), title, null,
IDEWorkbenchMessages.LinkedResourceEditor_convertionResults,
MessageDialog.INFORMATION,
new String[] { IDEWorkbenchMessages.linkedResourceEditor_OK },
0) {
@Override
protected boolean isResizable() {
return true;
}
@Override
protected Control createCustomArea(Composite comp) {
setShellStyle(getShellStyle() | SWT.RESIZE);
Composite parent = new Composite(comp, 0);
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.marginLeft = 2;
layout.numColumns = 1;
layout.verticalSpacing = 9;
parent.setLayout(layout);
parent.setLayoutData(new GridData(GridData.FILL_BOTH));
Text text = new Text(parent, SWT.BORDER | SWT.MULTI
| SWT.V_SCROLL | SWT.H_SCROLL);
text.setText(resultMessage.toString());
GridData data = new GridData(640, 300);
text.setLayoutData(data);
return parent;
}
};
dialog.open();
reparent(selectedResources);
}
private IPath convertToProperCase(IPath path) {
if (Platform.getOS().equals(Platform.OS_WIN32))
return Path.fromPortableString(path.toPortableString()
.toLowerCase());
return path;
}
/**
* @param resources
* @param selectedResources
*/
private void convertToRelative(ArrayList/* <IResource> */resources,
IResource[] selectedResources) {
ArrayList/* <String> */report = new ArrayList/* <String> */();
// first, try to use the automatic converter
ArrayList/* <IResource> */remaining = new ArrayList/* <IResource> */();
Iterator/* <IResource> */it = resources.iterator();
while (it.hasNext()) {
IResource res = (IResource) it.next();
IPath location = res.getLocation();
try {
IPath newLocation = URIUtil.toPath(res.getPathVariableManager().convertToRelative(URIUtil.toURI(location), true, null));
if (newLocation == null || newLocation.equals(location))
remaining.add(res);
else {
setLinkLocation(res, newLocation);
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_changedTo,
new Object[] {
res
.getProjectRelativePath()
.toPortableString(),
location.toOSString(),
newLocation
.toOSString() }));
}
} catch (CoreException e) {
remaining.add(res);
}
}
resources = remaining;
remaining = new ArrayList();
// try for each to match with an existing variable
String[] variables = fProject.getPathVariableManager()
.getPathVariableNames();
it = resources.iterator();
int amountLeft = 0;
while (it.hasNext()) {
IResource res = (IResource) it.next();
IPath location = res.getLocation();
int maxCount = 0;
int variable = -1;
for (int i = 0; i < variables.length; i++) {
IPath resolvePath = URIUtil.toPath(res.getPathVariableManager().resolveURI(
URIUtil.toURI(Path.fromOSString(variables[i]))));
if (resolvePath
.isPrefixOf(convertToProperCase(location))) {
int count = location
.matchingFirstSegments(resolvePath);
if (count > maxCount) {
maxCount = count;
variable = i;
}
}
}
if (variable != -1) {
IPath newLocation = Path.fromOSString(variables[variable])
.append(location.removeFirstSegments(maxCount));
try {
setLinkLocation(res, newLocation);
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_changedTo,
new Object[] {
res
.getProjectRelativePath()
.toPortableString(),
location.toOSString(),
newLocation
.toOSString() }));
} catch (CoreException e) {
variable = -1;
}
}
if (variable == -1) {
amountLeft++;
remaining.add(res);
}
}
resources = remaining;
if (amountLeft > 1) {
// try to generate a generic variable
it = resources.iterator();
IPath commonPath = null;
while (it.hasNext()) {
IResource res = (IResource) it.next();
IPath location = res.getLocation();
if (commonPath == null)
commonPath = location;
else {
int count = commonPath.matchingFirstSegments(location);
if (count < commonPath.segmentCount())
commonPath = commonPath.removeLastSegments(commonPath
.segmentCount()
- count);
}
if (commonPath.segmentCount() == 0)
break;
}
if (commonPath.segmentCount() > 1) {
String variableName = getSuitablePathVariable(commonPath);
try {
fProject.getPathVariableManager().setURIValue(variableName,
URIUtil.toURI(commonPath));
} catch (CoreException e) {
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_unableToCreateVariable,
variableName, commonPath
.toOSString()));
}
it = resources.iterator();
while (it.hasNext()) {
IResource res = (IResource) it.next();
IPath location = res.getLocation();
int commonCount = location
.matchingFirstSegments(commonPath);
IPath newLocation = Path.fromOSString(variableName).append(
location.removeFirstSegments(commonCount));
try {
setLinkLocation(res, newLocation);
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_changedTo,
new Object[] {
res
.getProjectRelativePath()
.toPortableString(),
location
.toOSString(),
newLocation
.toOSString() }));
} catch (CoreException e) {
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_unableToSetLinkLocationForResource,
res.getProjectRelativePath()
.toPortableString()));
}
}
} else {
report
.add(IDEWorkbenchMessages.LinkedResourceEditor_unableToFindCommonPathSegments);
it = resources.iterator();
while (it.hasNext()) {
IResource res = (IResource) it.next();
report.add(res.getProjectRelativePath().toPortableString());
}
}
} else if (!resources.isEmpty()) {
IResource res = (IResource) resources.get(0);
IPath resLocation = res.getLocation();
IPath commonPath = resLocation.removeLastSegments(1);
String variableName = getSuitablePathVariable(commonPath);
try {
fProject.getPathVariableManager().setURIValue(variableName,
URIUtil.toURI(commonPath));
} catch (CoreException e) {
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_unableToCreateVariable,
variableName, commonPath
.toPortableString()));
}
IPath location = res.getLocation();
int commonCount = location.matchingFirstSegments(commonPath);
IPath newLocation = Path.fromOSString(variableName).append(
location.removeFirstSegments(commonCount));
try {
setLinkLocation(res, newLocation);
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_changedTo,
new Object[] {
res.getProjectRelativePath()
.toPortableString(),
location.toOSString(),
newLocation.toOSString() }));
} catch (CoreException e) {
report
.add(NLS
.bind(
IDEWorkbenchMessages.LinkedResourceEditor_unableToSetLinkLocationForResource,
res.getProjectRelativePath()
.toPortableString()));
}
}
reportResult(
selectedResources,
report,
IDEWorkbenchMessages.LinkedResourceEditor_convertAbsolutePathLocations);
}
private String getSuitablePathVariable(IPath commonPath) {
String variableName = commonPath.lastSegment();
if (variableName == null) {
variableName = commonPath.getDevice();
if (variableName == null)
variableName = "ROOT"; //$NON-NLS-1$
else
variableName = variableName.substring(0, variableName.length() -1); // remove the tailing ':'
}
StringBuffer buf = new StringBuffer();
for (int i = 0; i < variableName.length(); i++) {
char c = variableName.charAt(i);
if (Character.isLetterOrDigit(c) || (c == '_'))
buf.append(c);
else
buf.append('_');
}
variableName = buf.toString();
int index = 1;
while (fProject.getPathVariableManager().isDefined(variableName)) {
variableName += index;
index++;
}
return variableName;
}
void editLocation() {
IResource resource = getSelectedResource()[0];
IPath location = resource.getRawLocation();
PathVariableDialog dialog = new PathVariableDialog(
fConvertAbsoluteButton.getShell(),
PathVariableDialog.EDIT_LINK_LOCATION, resource.getType(),
resource.getPathVariableManager(), null);
if (location != null)
dialog.setLinkLocation(location);
dialog.setResource(resource);
if (dialog.open() == Window.CANCEL) {
return;
}
location = Path.fromOSString(dialog.getVariableValue());
try {
setLinkLocation(resource, location);
} catch (Exception e) {
e.printStackTrace();
}
reparent(new IResource[] { resource });
}
void reparent(IResource[] resources) {
boolean changed = false;
for (int i = 0; i < resources.length; i++) {
IResource resource = resources[i];
boolean isBroken;
try {
isBroken = !exists(resource);
} catch (CoreException e) {
isBroken = true;
}
TreeMap/* <String, IResource> */container = null;
if (isBroken)
container = fBrokenResources;
else {
if (isAbsolute(resource))
container = fAbsoluteResources;
else
container = fFixedResources;
}
String fullPath = resource.getFullPath().toPortableString();
if (!container.containsKey(fullPath)) {
fBrokenResources.remove(fullPath);
fAbsoluteResources.remove(fullPath);
fFixedResources.remove(fullPath);
container.put(fullPath, resource);
changed = true;
}
}
if (changed)
fTree.refresh();
}
boolean initialized = false;
TreeMap/* <String, IResource> */fBrokenResources = new TreeMap/*
* <String,
* IResource
* >
*/();
TreeMap/* <String, IResource> */fAbsoluteResources = new TreeMap/*
* <String,
* IResource
* >
*/();
TreeMap/* <String, IResource> */fFixedResources = new TreeMap/*
* <String,
* IResource>
*/();
IProject fProject;
TreeViewer fTree;
Button fEditResourceButton;
Button fConvertAbsoluteButton;
Button fRemoveButton;
Image fixedImg = null;
Image brokenImg = null;
Image absoluteImg = null;
String FIXED;
String BROKEN;
String ABSOLUTE;
/**
* @return true
*/
public boolean performOk() {
return true;
}
/**
* @param enableLinking
*/
public void setEnabled(boolean enableLinking) {
}
/**
*
*/
public void reloadContent() {
refreshContent();
fTree.refresh();
updateSelection();
fTree.expandAll();
}
}