blob: cc21272fb719b5e0cdcd7bd254285719c9e8b8a9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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
* Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog font
* should be activated and used by other components.
*******************************************************************************/
package org.eclipse.ui.internal.ide.dialogs;
import java.util.Set;
import org.eclipse.core.resources.IPathVariableManager;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
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.graphics.Font;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
/**
* Dialog that prompts the user for defining a variable's name and value. It
* supports creating a new variable or editing an existing one. The difference
* between the two uses is just a matter of which messages to present to the
* user and whether the "Ok" button starts enabled or not.
*/
public class PathVariableDialog extends TitleAreaDialog {
// UI widgets
private Button okButton;
private Label variableNameLabel;
private Label variableValueLabel;
private Text variableNameField;
private Text variableValueField;
private Button fileButton;
private Button folderButton;
/**
* This dialog type: <code>NEW_VARIABLE</code> or
* <code>EXISTING_VARIABLE</code>.
*/
private int type;
/**
* The type of variable that can be edited in this dialog.
* <code>IResource.FILE</code> or <code>IResource.FOLDER</code>
*/
private int variableType;
/**
* The name of the variable being edited.
*/
private String variableName;
/**
* The value of the variable being edited.
*/
private String variableValue;
/**
* The original name of the variable being edited. It is used when testing
* if the current variable's name is already in use.
*/
private String originalName;
/**
* Used to select the proper message depending on the current mode
* (new/existing variable).
*/
private boolean newVariable;
/**
* Reference to the path variable manager. It is used for validating
* variable names.
*/
private IPathVariableManager pathVariableManager;
/**
* Set of variable names currently in use. Used when warning the user that
* the currently selected name is already in use by another variable.
*/
private Set namesInUse;
/**
* The current validation status. Its value can be one of the following:<ul>
* <li><code>IMessageProvider.NONE</code> (default);</li>
* <li><code>IMessageProvider.WARNING</code>;</li>
* <li><code>IMessageProvider.ERROR</code>;</li>
* </ul>
* Used when validating the user input.
*/
private int validationStatus;
/**
* The current validation message generated by the last
* call to a <code>validate</code> method.
*/
private String validationMessage;
/**
* Whether a variable name has been entered.
*/
private boolean nameEntered = false;
/**
* Whether a variable location has been entered.
*/
private boolean locationEntered = false;
/**
* The standard message to be shown when there are no problems being
* reported.
*/
final private String standardMessage;
/**
* Constant for defining this dialog as intended to create a new variable
* (value = 1).
*/
public final static int NEW_VARIABLE = 1;
/**
* Constant for defining this dialog as intended to edit an existing
* variable (value = 2).
*/
public final static int EXISTING_VARIABLE = 2;
/**
* Constructs a dialog for editing a new/existing path variable.
*
* @param parentShell the parent shell
* @param type the dialog type: <code>NEW_VARIABLE</code> or
* <code>EXISTING_VARIABLE</code>
* @param variableType the type of variable that can be edited in
* this dialog. <code>IResource.FILE</code> or <code>IResource.FOLDER</code>
* @param pathVariableManager a reference to the path variable manager
* @param namesInUse a set of variable names currently in use
*/
public PathVariableDialog(Shell parentShell, int type, int variableType,
IPathVariableManager pathVariableManager, Set namesInUse) {
super(parentShell);
this.type = type;
this.newVariable = type == NEW_VARIABLE;
this.variableName = ""; //$NON-NLS-1$
this.variableValue = ""; //$NON-NLS-1$
this.variableType = variableType;
this.pathVariableManager = pathVariableManager;
this.namesInUse = namesInUse;
if (newVariable)
this.standardMessage = IDEWorkbenchMessages.PathVariableDialog_message_newVariable;
else
this.standardMessage = IDEWorkbenchMessages.PathVariableDialog_message_existingVariable;
}
/**
* Configures this dialog's shell, setting the shell's text.
*
* @see org.eclipse.jface.window.Window#configureShell(Shell)
*/
protected void configureShell(Shell shell) {
super.configureShell(shell);
if (newVariable)
shell.setText(IDEWorkbenchMessages.PathVariableDialog_shellTitle_newVariable);
else
shell
.setText(IDEWorkbenchMessages.PathVariableDialog_shellTitle_existingVariable);
}
/**
* Creates and returns the contents of this dialog (except for the button bar).
*
* @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea
*/
protected Control createDialogArea(Composite parent) {
// top level composite
Composite parentComposite = (Composite) super.createDialogArea(parent);
// creates dialog area composite
Composite contents = createComposite(parentComposite);
// creates and lay outs dialog area widgets
createWidgets(contents, parent.getFont());
// validate possibly already incorrect variable definitions
if (type == EXISTING_VARIABLE) {
nameEntered = locationEntered = true;
validateVariableValue();
}
return contents;
}
/**
* Creates and configures this dialog's main composite.
*
* @param parentComposite parent's composite
* @return this dialog's main composite
*/
private Composite createComposite(Composite parentComposite) {
// creates a composite with standard margins and spacing
Composite contents = new Composite(parentComposite, SWT.NONE);
FormLayout layout = new FormLayout();
layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
contents.setLayout(layout);
contents.setFont(parentComposite.getFont());
if (newVariable)
setTitle(IDEWorkbenchMessages.PathVariableDialog_dialogTitle_newVariable);
else
setTitle(IDEWorkbenchMessages.PathVariableDialog_dialogTitle_existingVariable);
setMessage(standardMessage);
return contents;
}
/**
* Creates widgets for this dialog.
*
* @param parent the parent composite where to create widgets
* @param contents
*/
private void createWidgets(Composite contents, Font font) {
FormData data;
String nameLabelText = IDEWorkbenchMessages.PathVariableDialog_variableName;
String valueLabelText = IDEWorkbenchMessages.PathVariableDialog_variableValue;
// variable name label
variableNameLabel = new Label(contents, SWT.LEFT);
variableNameLabel.setText(nameLabelText);
data = new FormData();
variableNameLabel.setLayoutData(data);
variableNameLabel.setFont(font);
// variable value label
variableValueLabel = new Label(contents, SWT.LEFT);
variableValueLabel.setText(valueLabelText);
data = new FormData();
data.top = new FormAttachment(variableNameLabel,
convertVerticalDLUsToPixels(10));
variableValueLabel.setLayoutData(data);
variableValueLabel.setFont(font);
// the larger label will be used in the left attachments for the fields
Label largerLabel = nameLabelText.length() > valueLabelText.length() ? variableNameLabel
: variableValueLabel;
// variable name field
variableNameField = new Text(contents, SWT.SINGLE | SWT.BORDER);
variableNameField.setText(variableName);
data = new FormData();
data.width = convertWidthInCharsToPixels(50);
data.left = new FormAttachment(largerLabel,
convertHorizontalDLUsToPixels(5));
variableNameField.setLayoutData(data);
variableNameField.setFont(font);
variableNameField.setFocus();
variableNameField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent event) {
variableNameModified();
}
});
// variable value field
variableValueField = new Text(contents, SWT.SINGLE | SWT.BORDER);
variableValueField.setText(variableValue);
data = new FormData();
data.width = convertWidthInCharsToPixels(50);
data.left = new FormAttachment(largerLabel,
convertHorizontalDLUsToPixels(5));
data.top = new FormAttachment(variableNameLabel,
convertVerticalDLUsToPixels(10));
variableValueField.setLayoutData(data);
variableValueField.setFont(font);
variableValueField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent event) {
variableValueModified();
}
});
// select file path button
fileButton = new Button(contents, SWT.PUSH);
fileButton.setText(IDEWorkbenchMessages.PathVariableDialog_file);
if ((variableType & IResource.FILE) == 0)
fileButton.setEnabled(false);
data = setButtonFormLayoutData(fileButton);
data.top = new FormAttachment(variableNameLabel,
convertVerticalDLUsToPixels(10));
data.left = new FormAttachment(variableValueField,
convertHorizontalDLUsToPixels(10));
data.right = new FormAttachment(100, -5);
fileButton.setLayoutData(data);
fileButton.setFont(font);
fileButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
selectFile();
}
});
// select folder path button
folderButton = new Button(contents, SWT.PUSH);
folderButton.setText(IDEWorkbenchMessages.PathVariableDialog_folder);
if ((variableType & IResource.FOLDER) == 0)
folderButton.setEnabled(false);
data = setButtonFormLayoutData(folderButton);
data.top = new FormAttachment(variableValueLabel,
convertVerticalDLUsToPixels(10));
data.left = new FormAttachment(variableValueField,
convertHorizontalDLUsToPixels(10));
data.right = new FormAttachment(100, -5);
folderButton.setLayoutData(data);
folderButton.setFont(font);
folderButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
selectFolder();
}
});
}
/**
* Sets the <code>FormData</code> on the specified button to be one that is
* spaced for the current dialog page units. The method
* <code>initializeDialogUnits</code> must be called once before calling this
* method for the first time.
*
* @param button the button to set the <code>FormData</code>
* @return the <code>FormData</code> set on the specified button
*/
private FormData setButtonFormLayoutData(Button button) {
FormData data = new FormData();
int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
data.width = Math.max(widthHint, button.computeSize(SWT.DEFAULT,
SWT.DEFAULT, true).x);
button.setLayoutData(data);
return data;
}
/**
* Fires validations (variable name first) and updates enabled state for the
* "Ok" button accordingly.
*/
private void variableNameModified() {
// updates and validates the variable name
variableName = variableNameField.getText();
validationStatus = IMessageProvider.NONE;
okButton.setEnabled(validateVariableName() && validateVariableValue());
nameEntered = true;
}
/**
* Fires validations (variable value first) and updates enabled state for the
* "Ok" button accordingly.
*/
private void variableValueModified() {
// updates and validates the variable value
variableValue = variableValueField.getText().trim();
validationStatus = IMessageProvider.NONE;
okButton.setEnabled(validateVariableValue() && validateVariableName());
locationEntered = true;
}
/**
* Opens a dialog where the user can select a folder path.
*/
private void selectFolder() {
DirectoryDialog dialog = new DirectoryDialog(getShell());
dialog.setText(IDEWorkbenchMessages.PathVariableDialog_selectFolderTitle);
dialog.setMessage(IDEWorkbenchMessages.PathVariableDialog_selectFolderMessage);
dialog.setFilterPath(variableValue);
String res = dialog.open();
if (res != null) {
variableValue = new Path(res).makeAbsolute().toOSString();
variableValueField.setText(variableValue);
}
}
/**
* Opens a dialog where the user can select a file path.
*/
private void selectFile() {
FileDialog dialog = new FileDialog(getShell());
dialog.setText(IDEWorkbenchMessages.PathVariableDialog_selectFileTitle);
dialog.setFilterPath(variableValue);
String res = dialog.open();
if (res != null) {
variableValue = new Path(res).makeAbsolute().toOSString();
variableValueField.setText(variableValue);
}
}
/**
* Adds buttons to this dialog's button bar.
*
* @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar
*/
protected void createButtonsForButtonBar(Composite parent) {
okButton = createButton(parent, IDialogConstants.OK_ID,
IDialogConstants.OK_LABEL, true);
okButton.setEnabled(type == EXISTING_VARIABLE);
createButton(parent, IDialogConstants.CANCEL_ID,
IDialogConstants.CANCEL_LABEL, false);
}
/**
* Validates the current variable name, and updates this dialog's message.
*
* @return true if the name is valid, false otherwise
*/
private boolean validateVariableName() {
boolean allowFinish = false;
// if the current validationStatus is ERROR, no additional validation applies
if (validationStatus == IMessageProvider.ERROR)
return false;
// assumes everything will be ok
String message = standardMessage;
int newValidationStatus = IMessageProvider.NONE;
if (variableName.length() == 0) {
// the variable name is empty
if (nameEntered) {
// a name was entered before and is now empty
newValidationStatus = IMessageProvider.ERROR;
message = IDEWorkbenchMessages.PathVariableDialog_variableNameEmptyMessage;
}
} else {
IStatus status = pathVariableManager.validateName(variableName);
if (!status.isOK()) {
// the variable name is not valid
newValidationStatus = IMessageProvider.ERROR;
message = status.getMessage();
} else if (namesInUse.contains(variableName)
&& !variableName.equals(originalName)) {
// the variable name is already in use
message = IDEWorkbenchMessages.PathVariableDialog_variableAlreadyExistsMessage;
newValidationStatus = IMessageProvider.ERROR;
} else {
allowFinish = true;
}
}
// overwrite the current validation status / message only if everything is ok (clearing them)
// or if we have a more serious problem than the current one
if (validationStatus == IMessageProvider.NONE
|| newValidationStatus == IMessageProvider.ERROR) {
validationStatus = newValidationStatus;
validationMessage = message;
}
// only set the message here if it is not going to be set in
// validateVariableValue to avoid flashing.
if (allowFinish == false)
setMessage(validationMessage, validationStatus);
return allowFinish;
}
/**
* Validates the current variable value, and updates this dialog's message.
*
* @return true if the value is valid, false otherwise
*/
private boolean validateVariableValue() {
boolean allowFinish = false;
// if the current validationStatus is ERROR, no additional validation applies
if (validationStatus == IMessageProvider.ERROR)
return false;
// assumes everything will be ok
String message = standardMessage;
int newValidationStatus = IMessageProvider.NONE;
if (variableValue.length() == 0) {
// the variable value is empty
if (locationEntered) {
// a location value was entered before and is now empty
newValidationStatus = IMessageProvider.ERROR;
message = IDEWorkbenchMessages.PathVariableDialog_variableValueEmptyMessage;
}
} else if (!Path.EMPTY.isValidPath(variableValue)) {
// the variable value is an invalid path
message = IDEWorkbenchMessages.PathVariableDialog_variableValueInvalidMessage;
newValidationStatus = IMessageProvider.ERROR;
} else if (!new Path(variableValue).isAbsolute()) {
// the variable value is a relative path
message = IDEWorkbenchMessages.PathVariableDialog_pathIsRelativeMessage;
newValidationStatus = IMessageProvider.ERROR;
} else if (!IDEResourceInfoUtils.exists(variableValue)) {
// the path does not exist (warning)
message = IDEWorkbenchMessages.PathVariableDialog_pathDoesNotExistMessage;
newValidationStatus = IMessageProvider.WARNING;
allowFinish = true;
} else {
allowFinish = true;
}
// overwrite the current validation status / message only if everything is ok (clearing them)
// or if we have a more serious problem than the current one
if (validationStatus == IMessageProvider.NONE
|| newValidationStatus > validationStatus) {
validationStatus = newValidationStatus;
validationMessage = message;
}
setMessage(validationMessage, validationStatus);
return allowFinish;
}
/**
* Returns the variable name.
*
* @return the variable name
*/
public String getVariableName() {
return variableName;
}
/**
* Returns the variable value.
*
* @return the variable value
*/
public String getVariableValue() {
return variableValue;
}
/**
* Sets the variable name.
*
* @param variableName the new variable name
*/
public void setVariableName(String variableName) {
this.variableName = variableName.trim();
this.originalName = this.variableName;
}
/**
* Sets the variable value.
*
* @param variableValue the new variable value
*/
public void setVariableValue(String variableValue) {
this.variableValue = variableValue;
}
}