blob: ded36e453b6f9b9a9ba6f31837befa128ee22e45 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 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
*******************************************************************************/
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.IFolder;
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.Path;
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.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.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;
/**
* 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
*/
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 Button fWorkspaceButton;
protected Button fFileSystemButton;
protected Button fVariablesButton;
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 defaultOutputFile;
protected String outputFile;
protected String fileLabel = Messages.getString("ResourceSelectionBlock.0"); //$NON-NLS-1$
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 IFolder))
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());
}
}
}
/**
* 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(3, 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);
}
protected void updateResourceText(boolean useDefault)
{
if (useDefault)
{
resourceText.setText(defaultOutputFile == null ? "" : defaultOutputFile); //$NON-NLS-1$
}
else
{
resourceText.setText(outputFile == null ? "" : outputFile); //$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 null;
}
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();
if (path.startsWith("${workspace_loc:")) //$NON-NLS-1$
{
IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
try
{
path = manager.performStringSubstitution(path, false);
if (resourceType == IResource.FOLDER)
{
IContainer[] containers = root.findContainersForLocation(new Path(path));
if (containers.length > 0)
{
res = containers[0];
}
}
else if (resourceType == IResource.FILE)
{
IFile[] files = root.findFilesForLocation(new Path(path));
if (files.length > 0)
{
res = files[0];
}
}
}
catch (CoreException e)
{
}
}
else
{
res = root.findMember(path);
}
return res;
}
return null;
}
protected void handleResourceVariablesButtonSelected()
{
StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getShell());
dialog.open();
String variableText = dialog.getVariableExpression();
if (variableText != null)
{
resourceText.insert(variableText);
}
}
protected abstract void setDefaultResource();
@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;
}
}