/*******************************************************************************
* Copyright (c) 2009 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:
* IBM Corporation - initial API and implementation
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.debug.ui.pathmapper;
import java.util.*;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.ui.viewsupport.ScriptUILabelProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.Window;
import org.eclipse.php.internal.debug.core.pathmapper.BestMatchPathComparator;
import org.eclipse.php.internal.debug.core.pathmapper.PathEntry;
import org.eclipse.php.internal.debug.core.pathmapper.VirtualPath;
import org.eclipse.php.internal.debug.core.pathmapper.PathEntry.Type;
import org.eclipse.php.internal.debug.ui.PHPDebugUIImages;
import org.eclipse.php.internal.ui.IPHPHelpContextIds;
import org.eclipse.php.internal.ui.util.PHPPluginImages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
public class PathEntrySelectionDialog extends TrayDialog {
private static final Object[] EMPTY = new Object[0];
private static final Object EXTERNAL_CONTAINER = new Object();
private VirtualPath path;
private PathEntry[] pathEntries;
private PathEntry result;
private VirtualPath ignorePathResult;
private Font boldFont;
protected Button selectMappingBtn;
private TreeViewer entriesViewer;
protected Button ignoreMappingBtn;
private Text ignorePathText;
private Button configurePathBtn;
/**
* Constructs new path entry selection dialog
*
* @param shell
* Window shell
* @param path
* Abstract path of the file to match
* @param files
* Files to choose
*/
public PathEntrySelectionDialog(Shell shell, VirtualPath path,
PathEntry[] pathEntries) {
super(shell);
setShellStyle(getShellStyle() | SWT.RESIZE);
this.path = path;
this.pathEntries = pathEntries;
}
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(Messages.PathEntrySelectionDialog_0);
newShell.setImage(PHPDebugUIImages
.get(PHPDebugUIImages.IMG_OBJ_PATH_MAPPING));
PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
IPHPHelpContextIds.PATH_MAPPING);
}
protected Control createDialogArea(Composite parent) {
parent = (Composite) super.createDialogArea(parent);
GridLayout layout = (GridLayout) parent.getLayout();
layout.numColumns = 2;
initializeDialogUnits(parent);
FontData[] fontData = parent.getFont().getFontData();
for (FontData d : fontData) {
d.setStyle(SWT.BOLD);
}
boldFont = new Font(parent.getFont().getDevice(), fontData);
selectMappingBtn = new Button(parent, SWT.RADIO);
selectMappingBtn.setSelection(true);
selectMappingBtn
.setText(Messages.PathEntrySelectionDialog_1);
GridData layoutData = new GridData();
layoutData.horizontalSpan = 2;
selectMappingBtn.setLayoutData(layoutData);
selectMappingBtn.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
boolean enabled = selectMappingBtn.getSelection();
entriesViewer.getControl().setEnabled(enabled);
ignorePathText.setEnabled(!enabled);
configurePathBtn.setEnabled(!enabled);
validate();
}
});
Label label = new Label(parent, SWT.NONE);
layoutData = new GridData();
layoutData.horizontalSpan = 2;
layoutData.horizontalIndent = convertWidthInCharsToPixels(4);
layoutData.verticalAlignment = SWT.BEGINNING;
label.setLayoutData(layoutData);
label.setFont(boldFont);
label.setText(path.toString());
entriesViewer = new TreeViewer(parent, SWT.SINGLE | SWT.H_SCROLL
| SWT.V_SCROLL | SWT.BORDER);
layoutData = new GridData(GridData.FILL_BOTH);
layoutData.horizontalSpan = 2;
layoutData.verticalIndent = convertHeightInCharsToPixels(1);
layoutData.horizontalIndent = convertWidthInCharsToPixels(2);
layoutData.heightHint = convertHeightInCharsToPixels(20);
layoutData.widthHint = convertWidthInCharsToPixels(70);
entriesViewer.getControl().setLayoutData(layoutData);
entriesViewer.setContentProvider(new ContentProvider());
entriesViewer.setLabelProvider(new LabelProvider());
entriesViewer.setSorter(new Sorter());
entriesViewer.setInput(this);
entriesViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
validate();
}
});
entriesViewer.expandAll();
ignoreMappingBtn = new Button(parent, SWT.RADIO);
ignoreMappingBtn
.setText(Messages.PathEntrySelectionDialog_2);
layoutData = new GridData();
layoutData.horizontalSpan = 2;
ignoreMappingBtn.setLayoutData(layoutData);
ignoreMappingBtn.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
boolean enabled = ignoreMappingBtn.getSelection();
entriesViewer.getControl().setEnabled(!enabled);
ignorePathText.setEnabled(enabled);
configurePathBtn.setEnabled(enabled);
validate();
}
});
ignorePathText = new Text(parent, SWT.BORDER | SWT.READ_ONLY);
ignorePathText.setEnabled(false);
layoutData = new GridData(GridData.FILL_HORIZONTAL);
layoutData.horizontalIndent = convertWidthInCharsToPixels(2);
layoutData.widthHint = convertWidthInCharsToPixels(70);
ignorePathText.setLayoutData(layoutData);
ignorePathResult = path.clone();
ignorePathText.setText(getIgnorePathString(ignorePathResult));
configurePathBtn = new Button(parent, SWT.PUSH);
configurePathBtn.setEnabled(false);
configurePathBtn.setText(Messages.PathEntrySelectionDialog_3);
configurePathBtn.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
ConfigurePathDialog dialog = new ConfigurePathDialog(
ignorePathResult);
if (dialog.open() == Window.OK) {
ignorePathResult = dialog.getResult();
ignorePathText
.setText(getIgnorePathString(ignorePathResult));
validate();
}
}
});
return parent;
}
protected void createButtonsForButtonBar(Composite parent) {
Button okButton = createButton(parent, IDialogConstants.OK_ID,
IDialogConstants.OK_LABEL, true);
okButton.setEnabled(false);
createButton(parent, IDialogConstants.CANCEL_ID, Messages.PathEntrySelectionDialog_4,
false);
}
private String getIgnorePathString(VirtualPath path) {
if (path.getSegmentsCount() == PathEntrySelectionDialog.this.path
.getSegmentsCount()) {
return path.toString();
}
return new StringBuilder(path.toString()).append(
path.getSeparatorChar()).append('*').toString();
}
/**
* Returns selected path entry
*
* @return path entry
*/
public PathEntry getResult() {
return result;
}
/**
* Returns ignored path result
*/
public VirtualPath getIgnoreResult() {
return ignorePathResult;
}
protected void validate() {
Button okButton = getButton(IDialogConstants.OK_ID);
okButton.setEnabled(false);
result = null;
if (selectMappingBtn.getSelection()) {
Object selectedElement = ((IStructuredSelection) entriesViewer
.getSelection()).getFirstElement();
if (selectedElement instanceof PathEntry) {
okButton.setEnabled(true);
result = (PathEntry) selectedElement;
}
} else {
okButton.setEnabled(true);
}
}
/**
* Ignored paths configuration dialog
*/
class ConfigurePathDialog extends Dialog {
private VirtualPath result;
private Text pathText;
protected ConfigurePathDialog(VirtualPath path) {
super(PathEntrySelectionDialog.this.getShell());
setShellStyle(getShellStyle() | SWT.RESIZE);
this.result = path;
}
public VirtualPath getResult() {
return result;
}
protected Control createDialogArea(Composite parent) {
parent = (Composite) super.createDialogArea(parent);
initializeDialogUnits(parent);
getShell().setText(Messages.PathEntrySelectionDialog_5);
getShell()
.setImage(
PHPDebugUIImages
.get(PHPDebugUIImages.IMG_OBJ_PATH_MAPPING));
TreeViewer treeViewer = new TreeViewer(parent, SWT.SINGLE
| SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
GridData layoutData = new GridData(GridData.FILL_BOTH);
layoutData.heightHint = convertHeightInCharsToPixels(15);
layoutData.widthHint = convertWidthInCharsToPixels(60);
treeViewer.getControl().setLayoutData(layoutData);
treeViewer.setContentProvider(new ContentProvider());
treeViewer.setLabelProvider(new LabelProvider());
treeViewer.setInput(Integer.valueOf(0));
treeViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
Integer segmentNum = (Integer) ((IStructuredSelection) event
.getSelection()).getFirstElement();
if (segmentNum != null) {
result = path.clone();
for (int i = path.getSegmentsCount(); i > segmentNum; --i) {
result.removeLastSegment();
}
pathText.setText(getIgnorePathString(result));
}
}
});
pathText = new Text(parent, SWT.BORDER | SWT.READ_ONLY);
layoutData = new GridData(GridData.FILL_HORIZONTAL);
pathText.setLayoutData(layoutData);
treeViewer.setSelection(new StructuredSelection(result
.getSegmentsCount()));
treeViewer.expandAll();
return parent;
}
class ContentProvider implements ITreeContentProvider {
public Object[] getChildren(Object parentElement) {
Integer segmentNum = (Integer) parentElement;
if (segmentNum < path.getSegmentsCount()) {
return new Object[] { segmentNum + 1 };
}
return EMPTY;
}
public Object getParent(Object element) {
Integer segmentNum = (Integer) element;
if (segmentNum > 0) {
return segmentNum - 1;
}
return null;
}
public boolean hasChildren(Object element) {
Integer segmentNum = (Integer) element;
return (segmentNum < path.getSegmentsCount());
}
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
}
}
class LabelProvider extends org.eclipse.jface.viewers.LabelProvider {
private Map<String, Image> images = new HashMap<String, Image>();
public Image getImage(Object element) {
Integer segmentNum = (Integer) element;
if (segmentNum < path.getSegmentsCount()) {
return PlatformUI.getWorkbench().getSharedImages()
.getImage(ISharedImages.IMG_OBJ_FOLDER);
}
String lastSegment = path.getLastSegment();
int idx = lastSegment.lastIndexOf('.');
if (idx != -1) {
String extension = lastSegment.substring(idx);
if (images.containsKey(extension)) {
return images.get(extension);
}
Program p = Program.findProgram(extension);
if (p != null) {
ImageData data = p.getImageData();
if (data != null) {
Image image = new Image(Display.getDefault(), data);
images.put(extension, image);
return image;
}
}
}
return PlatformUI.getWorkbench().getSharedImages().getImage(
ISharedImages.IMG_OBJ_FILE);
}
public String getText(Object element) {
Integer segmentNum = (Integer) element;
return path.getSegments()[segmentNum - 1];
}
public void dispose() {
Iterator<Image> i = images.values().iterator();
while (i.hasNext()) {
i.next().dispose();
}
}
}
}
/**
* Sorter for path entries by relevancy
*/
class Sorter extends ViewerSorter {
private BestMatchPathComparator comparator;
public Sorter() {
comparator = new BestMatchPathComparator(path);
}
public int compare(Viewer viewer, Object e1, Object e2) {
if (e1 instanceof PathEntry && e2 instanceof PathEntry) {
return comparator.compare((PathEntry) e1, (PathEntry) e2);
}
if (e1 == EXTERNAL_CONTAINER) {
return 1;
}
if (e1 instanceof IResource) {
return -1;
}
return 0;
}
}
/**
* Path entries label provider
*/
class LabelProvider extends ScriptUILabelProvider {
public Image getImage(Object element) {
if (element instanceof IBuildpathEntry) {
IBuildpathEntry includePathEntry = (IBuildpathEntry) element;
if (includePathEntry.getEntryKind() == IBuildpathEntry.BPE_VARIABLE) {
return PHPPluginImages
.get(PHPPluginImages.IMG_OBJS_ENV_VAR);
} else {
return PHPPluginImages
.get(PHPPluginImages.IMG_OBJS_LIBRARY);
}
}
if (element instanceof PathEntry) {
return PHPPluginImages.get(PHPPluginImages.IMG_OBJS_CUNIT);
}
return super.getImage(element);
}
public String getText(Object element) {
if (element == EXTERNAL_CONTAINER) {
return Messages.PathEntrySelectionDialog_6;
}
if (element instanceof IBuildpathEntry) {
IBuildpathEntry includePathEntry = (IBuildpathEntry) element;
return EnvironmentPathUtils.getLocalPathString(includePathEntry
.getPath());
}
if (!(element instanceof PathEntry)) {
return super.getText(element);
}
PathEntry entry = (PathEntry) element;
String path = entry.getResolvedPath();
if (entry.getType() == Type.WORKSPACE) {
VirtualPath tmpPath = entry.getAbstractPath().clone();
tmpPath.removeFirstSegment();
path = tmpPath.toString();
if (path.startsWith("/")) { //$NON-NLS-1$
path = path.substring(1);
}
}
if (entry.getType() == Type.INCLUDE_FOLDER
|| entry.getType() == Type.INCLUDE_VAR) {
IBuildpathEntry includePathEntry = (IBuildpathEntry) entry
.getContainer();
String includePath = EnvironmentPathUtils
.getLocalPathString(includePathEntry.getPath());
if (includePathEntry.getEntryKind() == IBuildpathEntry.BPE_VARIABLE) {
IPath p = DLTKCore.getResolvedVariablePath(includePathEntry
.getPath());
if (p != null) {
includePath = p.toOSString();
}
}
if (includePath != null && path.startsWith(includePath)) {
path = path.substring(includePath.length());
}
if (path.startsWith("/")) { //$NON-NLS-1$
path = path.substring(1);
}
}
return path;
}
}
/**
* Path entries content provider
*/
class ContentProvider implements ITreeContentProvider {
public Object[] getChildren(Object parentElement) {
if (parentElement == PathEntrySelectionDialog.this) {
Set<Object> containers = new HashSet<Object>();
for (PathEntry entry : pathEntries) {
if (entry.getType() == Type.EXTERNAL) {
containers.add(EXTERNAL_CONTAINER);
} else if (entry.getType() == Type.INCLUDE_VAR
|| entry.getType() == Type.INCLUDE_FOLDER) {
containers.add(entry.getContainer());
} else if (entry.getType() == Type.WORKSPACE) {
containers.add(((IResource) entry.getContainer())
.getProject());
}
}
return containers.toArray();
}
if (parentElement instanceof PathEntry) {
return EMPTY;
}
Set<PathEntry> entries = new HashSet<PathEntry>();
for (PathEntry entry : pathEntries) {
if (entry.getType() == Type.EXTERNAL
&& parentElement == EXTERNAL_CONTAINER) {
entries.add(entry);
} else if ((entry.getType() == Type.INCLUDE_VAR || entry
.getType() == Type.INCLUDE_FOLDER)
&& entry.getContainer() == parentElement) {
entries.add(entry);
} else if (entry.getType() == Type.WORKSPACE
&& ((IResource) entry.getContainer()).getProject() == parentElement) {
entries.add(entry);
}
}
return entries.toArray();
}
public Object getParent(Object element) {
if (element == PathEntrySelectionDialog.this) {
return null;
}
if (element instanceof PathEntry) {
PathEntry entry = (PathEntry) element;
if (entry.getType() == Type.EXTERNAL) {
return EXTERNAL_CONTAINER;
} else if (entry.getType() == Type.INCLUDE_VAR
|| entry.getType() == Type.INCLUDE_FOLDER) {
return entry.getContainer();
} else if (entry.getType() == Type.WORKSPACE) {
return ((IResource) entry.getContainer()).getProject();
}
}
for (PathEntry entry : pathEntries) {
if (entry.getType() == Type.EXTERNAL
&& element == EXTERNAL_CONTAINER) {
return entry;
} else if (entry.getType() == Type.INCLUDE_VAR
|| entry.getType() == Type.INCLUDE_FOLDER
&& entry.getContainer() == element) {
return entry;
} else if (entry.getType() == Type.WORKSPACE
&& ((IResource) entry.getContainer()).getProject() == element) {
return entry;
}
}
return null;
}
public boolean hasChildren(Object element) {
if (element instanceof PathEntry) {
return false;
}
return true;
}
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
}