blob: 1b56860deaae54385f32d7192513aa8a9c3c0de9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2010 Chase Technology Ltd - http://www.chasetechnology.co.uk
* 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:
* Doug Satchwell (Chase Technology Ltd) - initial API and implementation
* Stuart Harper - bug 264788 - added "open files" selector
* David Carver (STAR) - bug 264788 - pulled up getFileExtensions from InputFileBlock
* David Carver (Intalio) - clean up find bugs
*******************************************************************************/
package org.eclipse.wst.xsl.internal.debug.ui;
import java.io.File;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.debug.ui.StringVariableSelectionDialog;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.DirectoryDialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceComparator;
import org.eclipse.wst.xsl.core.internal.util.XMLContentType;
/**
* A block that shows a text box with buttons for browsing workspace or the
* filesystem in order to populate the text box with a file path.
*
* @author Doug Satchwell
* @since 1.0
*/
public abstract class ResourceSelectionBlock extends
AbstractLaunchConfigurationTab {
protected static final int ERROR_DIRECTORY_NOT_SPECIFIED = 1;
protected static final int ERROR_DIRECTORY_DOES_NOT_EXIST = 2;
protected static final int GROUP_NAME = 3;
protected static final int USE_DEFAULT_RADIO = 4;
protected static final int USE_OTHER_RADIO = 5;
protected static final int DIRECTORY_DIALOG_MESSAGE = 6;
protected static final int WORKSPACE_DIALOG_MESSAGE = 7;
protected static final int VARIABLES_BUTTON = 8;
protected static final int FILE_SYSTEM_BUTTON = 9;
protected static final int WORKSPACE_BUTTON = 10;
protected static final int WORKSPACE_DIALOG_TITLE = 11;
protected static final int OPENFILES_BUTTON = 12;
protected static final int OPENFILES_DIALOG_TITLE = 13;
protected Button fWorkspaceButton;
protected Button fFileSystemButton;
protected Button fVariablesButton;
protected Button fOpenFilesButton;
protected Button useDefaultCheckButton;
protected Text resourceText;
protected WidgetListener widgetListener = new WidgetListener();
private ILaunchConfiguration fLaunchConfiguration;
protected final boolean showDefault;
private final int resourceType;
private final boolean mustExist;
protected boolean required;
protected String defaultResource;
protected String resource;
protected String fileLabel = Messages.ResourceSelectionBlock_0;
private final ISelectionStatusValidator validator = new ISelectionStatusValidator() {
public IStatus validate(Object[] selection) {
if (selection.length == 0) {
return new Status(IStatus.ERROR, XSLDebugUIPlugin.PLUGIN_ID, 0,
"", null); //$NON-NLS-1$
}
for (int i = 0; i < selection.length; i++) {
if (resourceType == IResource.FOLDER
&& !(selection[i] instanceof IContainer))
return new Status(IStatus.ERROR,
XSLDebugUIPlugin.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
else if (resourceType == IResource.FILE
&& !(selection[i] instanceof IFile))
return new Status(IStatus.ERROR,
XSLDebugUIPlugin.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
}
return new Status(IStatus.OK, XSLDebugUIPlugin.PLUGIN_ID, 0,
"", null); //$NON-NLS-1$
}
};
class WidgetListener extends SelectionAdapter implements ModifyListener {
public void modifyText(ModifyEvent e) {
textModified();
updateLaunchConfigurationDialog();
}
@Override
public void widgetSelected(SelectionEvent e) {
Object source = e.getSource();
if (source == fWorkspaceButton) {
handleWorkspaceResourceBrowseButtonSelected();
} else if (source == fFileSystemButton) {
handleExternalResourceBrowseButtonSelected();
} else if (source == fVariablesButton) {
handleResourceVariablesButtonSelected();
} else if (source == useDefaultCheckButton) {
updateResourceText(useDefaultCheckButton.getSelection());
} else if (source == fOpenFilesButton) {
handleOpenFilesResourceBrowseButtonSelected();
}
}
}
/**
* Same as <code>new ResourceSelectionBlock(true)</code>
*/
public ResourceSelectionBlock() {
this(true);
}
/**
* Same as
* <code>new ResourceSelectionBlock(IResource.FOLDER,showDefault)</code>
*
* @param showDefault
* true if this should have a 'Show Default' button
*/
public ResourceSelectionBlock(boolean showDefault) {
this(IResource.FOLDER, showDefault);
}
/**
* Same as
* <code>new ResourceSelectionBlock(resourceType,showDefault,true)</code>
*
* @param resourceType
* the type of resource to select - IResource.FOLDER or
* IResource.FILE
* @param showDefault
* true if this should have a 'Show Default' button
*/
public ResourceSelectionBlock(int resourceType, boolean showDefault) {
this(resourceType, showDefault, true);
}
/**
* Same as
* <code>new ResourceSelectionBlock(resourceType,showDefault,required,true)</code>
*
* @param resourceType
* the type of resource to select - IResource.FOLDER or
* IResource.FILE
* @param showDefault
* true if this should have a 'Show Default' button
* @param required
* true if a blank text box is invalid
*/
public ResourceSelectionBlock(int resourceType, boolean showDefault,
boolean required) {
this(resourceType, showDefault, required, true);
}
/**
* Create a new instance of this.
*
* @param resourceType
* the type of resource to select - IResource.FOLDER or
* IResource.FILE
* @param showDefault
* true if this should have a 'Show Default' button
* @param required
* true if a blank text box is invalid
* @param mustExist
* true of the selected resource must already exist
*/
public ResourceSelectionBlock(int resourceType, boolean showDefault,
boolean required, boolean mustExist) {
super();
this.showDefault = showDefault;
this.resourceType = resourceType;
this.required = required;
this.mustExist = mustExist;
}
public void createControl(Composite parent) {
Composite group = createContainer(parent);
setControl(group);
createContents(group);
}
protected Composite createContainer(Composite parent) {
Group group = new Group(parent, SWT.NONE);
group.setText(getMessage(GROUP_NAME));
// TODO PlatformUI.getWorkbench().getHelpSystem().setHelp...
GridLayout groupLayout = new GridLayout();
groupLayout.numColumns = 2;
groupLayout.makeColumnsEqualWidth = false;
group.setLayout(groupLayout);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
group.setLayoutData(gd);
group.setFont(parent.getFont());
return group;
}
protected void createContents(Composite parent) {
createCheckboxAndText(parent);
createButtons(parent);
}
protected void createCheckboxAndText(Composite parent) {
if (showDefault) {
useDefaultCheckButton = createCheckButton(parent,
getMessage(USE_DEFAULT_RADIO));
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalSpan = 2;
useDefaultCheckButton.setLayoutData(gd);
useDefaultCheckButton.addSelectionListener(widgetListener);
}
Composite specificFileComp = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginWidth = 0;
if (showDefault)
layout.marginLeft = 20;
else
layout.marginLeft = 0;
layout.marginHeight = 0;
specificFileComp.setLayout(layout);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
specificFileComp.setLayoutData(gd);
if (showDefault) {
Label label = new Label(specificFileComp, SWT.NONE);
label.setText(fileLabel);
}
resourceText = new Text(specificFileComp, SWT.SINGLE | SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = showDefault ? 1 : 2;
resourceText.setLayoutData(gd);
resourceText.setFont(parent.getFont());
resourceText.addModifyListener(widgetListener);
}
protected void createButtons(Composite parent) {
// filler
new Label(parent, SWT.NONE);
Composite buttonComp = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(4, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
buttonComp.setLayout(layout);
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
gd.horizontalSpan = 1;
buttonComp.setLayoutData(gd);
buttonComp.setFont(parent.getFont());
fWorkspaceButton = createPushButton(buttonComp,
getMessage(WORKSPACE_BUTTON), null);
fWorkspaceButton.addSelectionListener(widgetListener);
fFileSystemButton = createPushButton(buttonComp,
getMessage(FILE_SYSTEM_BUTTON), null);
fFileSystemButton.addSelectionListener(widgetListener);
fVariablesButton = createPushButton(buttonComp,
getMessage(VARIABLES_BUTTON), null);
fVariablesButton.addSelectionListener(widgetListener);
fOpenFilesButton = createPushButton(buttonComp,
getMessage(OPENFILES_BUTTON), null);
fOpenFilesButton.addSelectionListener(widgetListener);
}
protected void updateResourceText(boolean useDefault) {
if (useDefault) {
resourceText
.setText(defaultResource == null ? "" : defaultResource); //$NON-NLS-1$
} else {
resourceText.setText(resource == null ? "" : resource); //$NON-NLS-1$
}
resourceText.setEnabled(!useDefault);
fFileSystemButton.setEnabled(!useDefault);
fVariablesButton.setEnabled(!useDefault);
fWorkspaceButton.setEnabled(!useDefault);
}
@Override
public void dispose() {
}
protected void handleExternalResourceBrowseButtonSelected() {
String currentWorkingDir = getText();
String selected = null;
if (resourceType == IResource.FOLDER) {
DirectoryDialog dialog = new DirectoryDialog(getShell());
dialog.setMessage(getMessage(DIRECTORY_DIALOG_MESSAGE));
if (!currentWorkingDir.trim().equals("")) //$NON-NLS-1$
{
File path = new File(currentWorkingDir);
if (path.exists()) {
dialog.setFilterPath(currentWorkingDir);
}
}
selected = dialog.open();
} else {
FileDialog dialog = new FileDialog(getShell());
if (!currentWorkingDir.trim().equals("")) //$NON-NLS-1$
{
File path = new File(currentWorkingDir);
if (path.exists()) {
dialog.setFilterPath(currentWorkingDir);
}
}
String[] fileExtensions = getFileExtensions();
if (fileExtensions != null) {
String[] filterExtensions = new String[fileExtensions.length];
for (int i = 0; i < fileExtensions.length; i++) {
String ext = fileExtensions[i];
filterExtensions[i] = "*." + ext; //$NON-NLS-1$
}
dialog.setFilterExtensions(filterExtensions);
}
selected = dialog.open();
}
if (selected != null) {
resourceText.setText(selected);
}
}
protected String[] getFileExtensions() {
return new XMLContentType().getFileExtensions();
}
protected void handleOpenFilesResourceBrowseButtonSelected() {
String path = openFileListResourceDialog();
if (path != null)
setText("${workspace_loc:" + path + "}"); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Opens a dialog displaying a list of all XML files in the editor and
* allows the user to select one of them.
*
* @return The path to the selected XML file or null if none was chosen.
*/
protected String openFileListResourceDialog() {
IEditorReference[] editors = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage()
.getEditorReferences();
String[] paths = filterOpenEditorsByFileExtension(editors);
ElementListSelectionDialog dialog = new ElementListSelectionDialog(
getShell(), new LabelProvider());
dialog.setTitle(getMessage(OPENFILES_DIALOG_TITLE));
dialog.setElements(paths);
dialog.open();
return (String) dialog.getFirstResult();
}
private String[] filterOpenEditorsByFileExtension(IEditorReference[] editors) {
String[] paths = new String[editors.length];
String[] fileExts = getFileExtensions();
for (int i = 0; i < editors.length; i++) {
IEditorReference currentEditor = editors[i];
IEditorPart editorPart = currentEditor.getEditor(true);
IFile file = (IFile) editorPart.getEditorInput().getAdapter(
IFile.class);
if (file != null) {
IPath path = file.getFullPath();
paths[i] = getEditorPath(path, fileExts);
}
}
return paths;
}
private String getEditorPath(IPath filePath, String[] fileExts) {
if (fileExts == null || fileExts.length == 0) {
return filePath.toOSString();
}
String path = null;
for (int cnt = 0; cnt < fileExts.length; cnt++) {
if (filePath.getFileExtension().equals(fileExts[cnt])) {
path = filePath.toOSString();
break;
}
}
return path;
}
protected void handleWorkspaceResourceBrowseButtonSelected() {
IPath path = openWorkspaceResourceDialog();
if (path != null)
setText("${workspace_loc:" + path.toString() + "}"); //$NON-NLS-1$ //$NON-NLS-2$
}
protected IPath openWorkspaceResourceDialog() {
IResource currentResource = getResource();
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(
getShell(), new WorkbenchLabelProvider(),
new WorkbenchContentProvider());
dialog.setTitle(getMessage(WORKSPACE_DIALOG_TITLE));
dialog.setMessage(getMessage(WORKSPACE_DIALOG_MESSAGE));
dialog.setValidator(validator);
dialog.addFilter(new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement,
Object element) {
if (element instanceof IContainer)
return true;
if (resourceType != IResource.FILE)
return false;
IFile file = (IFile) element;
String[] extensions = getFileExtensions();
if (extensions == null)
return true;
String fileExt = file.getFileExtension();
if (fileExt != null) {
for (String ext : extensions) {
if (fileExt.equalsIgnoreCase(ext))
return true;
}
}
return false;
}
});
ViewerFilter filter = getResourceFilter();
if (filter != null)
dialog.addFilter(filter);
dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
dialog.setInitialSelection(currentResource);
dialog.setComparator(new ResourceComparator(ResourceComparator.NAME));
dialog.setAllowMultiple(false);
if (dialog.open() == Window.OK) {
Object[] elements = dialog.getResult();
if (elements.length > 0)
return ((IResource) elements[0]).getFullPath();
}
return null;
}
protected ViewerFilter getResourceFilter() {
return null;
}
/**
* Returns the selected workspace container,or <code>null</code>
*/
protected IResource getResource() {
String path = getText();
if (path.length() > 0) {
IResource res = null;
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
try {
if (path.startsWith("${workspace_loc:")) //$NON-NLS-1$
{
IStringVariableManager manager = VariablesPlugin
.getDefault().getStringVariableManager();
path = manager.performStringSubstitution(path, false);
}
File f = new File(path);
if (resourceType == IResource.FOLDER) {
IContainer[] containers = root
.findContainersForLocationURI(f.toURI());
if (containers.length > 0) {
res = containers[0];
}
} else if (resourceType == IResource.FILE) {
IFile[] files = root.findFilesForLocationURI(f.toURI());
if (files.length > 0) {
res = files[0];
}
}
return res;
} catch (CoreException e) {
XSLDebugUIPlugin.log(e);
}
}
return null;
}
protected void handleResourceVariablesButtonSelected() {
StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(
getShell());
dialog.open();
String variableText = dialog.getVariableExpression();
if (variableText != null) {
resourceText.insert(variableText);
}
}
@Override
public boolean isValid(ILaunchConfiguration config) {
setErrorMessage(null);
setMessage(null);
// if variables are present, we cannot resolve the directory
String workingDirPath = getText();
if (workingDirPath.indexOf("${") >= 0) //$NON-NLS-1$
{
IStringVariableManager manager = VariablesPlugin.getDefault()
.getStringVariableManager();
try {
manager.validateStringVariables(workingDirPath);
if (mustExist) {
String path = manager
.performStringSubstitution(workingDirPath);
validateResource(path);
}
} catch (CoreException e) {
setErrorMessage(e.getMessage());
return false;
}
} else if (mustExist && workingDirPath.length() > 0) {
return validateResource(workingDirPath);
} else if (required && workingDirPath.length() == 0) {
setErrorMessage(getMessage(ERROR_DIRECTORY_NOT_SPECIFIED));
}
return true;
}
protected boolean validateResource(String workingDirPath) {
if (resourceType == IResource.FOLDER) {
IContainer container = (IContainer) getResource();
if (container == null) {
File dir = new File(workingDirPath);
if (dir.isDirectory()) {
return true;
}
} else
return true;
} else if (resourceType == IResource.FILE) {
File file = new File(workingDirPath);
if (file.isFile()) {
return true;
}
}
setErrorMessage(getMessage(ERROR_DIRECTORY_DOES_NOT_EXIST));
return false;
}
protected abstract String getMessage(int type);
protected void textModified() {
}
protected String getText() {
return resourceText.getText().trim();
}
protected void setText(String text) {
resourceText.setText(text);
}
protected void setLaunchConfiguration(ILaunchConfiguration config) {
fLaunchConfiguration = config;
}
protected ILaunchConfiguration getLaunchConfiguration() {
return fLaunchConfiguration;
}
}