package org.erlide.ui.prefs;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
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.DirectoryDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.erlide.runtime.runtimeinfo.RuntimeInfo;
import org.erlide.ui.dialogs.fields.DialogField;
import org.erlide.ui.dialogs.fields.IDialogFieldListener;
import org.erlide.ui.dialogs.fields.IListAdapter;
import org.erlide.ui.dialogs.fields.IStringButtonAdapter;
import org.erlide.ui.dialogs.fields.ListDialogField;
import org.erlide.ui.dialogs.fields.StringButtonDialogField;
import org.erlide.ui.dialogs.fields.StringDialogField;
import org.erlide.ui.util.StatusInfo;
public class AddRuntimeDialog extends StatusDialog implements IListAdapter<String> {
public static class StringLabelProvider implements ILabelProvider {
@Override
public Image getImage(final Object element) {
return null;
}
@Override
public String getText(final Object element) {
return (String) element;
}
@Override
public void addListener(final ILabelProviderListener listener) {
}
@Override
public void dispose() {
}
@Override
public boolean isLabelProperty(final Object element, final String property) {
return false;
}
@Override
public void removeListener(final ILabelProviderListener listener) {
}
}
private final IAddDialogRequestor<RuntimeInfo> fRequestor;
private final RuntimeInfo fEditedRuntime;
private StringDialogField fName;
private StringButtonDialogField fOtpHome;
private ListDialogField<String> fCodePath;
private StringDialogField fArgs;
private final IStatus[] fStatuses;
public AddRuntimeDialog(final IAddDialogRequestor<RuntimeInfo> requestor,
final Shell shell, final RuntimeInfo editedVM) {
super(shell);
setShellStyle(getShellStyle() | SWT.RESIZE);
fRequestor = requestor;
fStatuses = new IStatus[5];
for (int i = 0; i < fStatuses.length; i++) {
fStatuses[i] = new StatusInfo();
}
fEditedRuntime = editedVM;
}
/**
* @see Windows#configureShell
*/
@Override
protected void configureShell(final Shell newShell) {
super.configureShell(newShell);
// PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
// IJavaDebugHelpContextIds.EDIT_JRE_DIALOG);
}
protected void createFieldListeners() {
fOtpHome.setDialogFieldListener(new IDialogFieldListener() {
@Override
public void dialogFieldChanged(final DialogField field) {
setLocationStatus(validateLocation());
updateStatusLine();
}
});
fName.setDialogFieldListener(new IDialogFieldListener() {
@Override
public void dialogFieldChanged(final DialogField field) {
setNameStatus(validateName());
updateStatusLine();
}
});
}
protected String getBackendName() {
return fName.getText();
}
@Override
protected Control createDialogArea(final Composite ancestor) {
fOtpHome = new StringButtonDialogField(new IStringButtonAdapter() {
@Override
public void changeControlPressed(final DialogField field) {
browseForInstallDir();
}
});
fOtpHome.setLabelText("Location"); //$NON-NLS-1$
fOtpHome.setButtonLabel("&Browse..."); //$NON-NLS-1$
fName = new StringDialogField();
fName.setLabelText(RuntimePreferenceMessages.addDialog_ertsName);
final String[] buttons = new String[] { RuntimePreferenceMessages.addDialog_add,
RuntimePreferenceMessages.addDialog_remove, "Move up", "Move down" };
fCodePath = new ListDialogField<>(this, buttons, new StringLabelProvider());
fCodePath.setLabelText("Code path");
// TODO enable this when it will work (#163)
fCodePath.setEnabled(false);
fArgs = new StringDialogField();
fArgs.setLabelText("E&xtra args"); //$NON-NLS-1$
final Composite parent = (Composite) super.createDialogArea(ancestor);
((GridLayout) parent.getLayout()).numColumns = 3;
fOtpHome.doFillIntoGrid(parent, 3);
fName.doFillIntoGrid(parent, 3);
fCodePath.doFillIntoGrid(parent, 3);
fArgs.doFillIntoGrid(parent, 3);
final Text t = fName.getTextControl(parent);
final GridData gd = (GridData) t.getLayoutData();
gd.grabExcessHorizontalSpace = true;
gd.widthHint = convertWidthInCharsToPixels(50);
initializeFields();
createFieldListeners();
applyDialogFont(parent);
return parent;
}
@Override
public void create() {
super.create();
fName.setFocus();
}
private void initializeFields() {
if (fEditedRuntime == null) {
fName.setText(""); //$NON-NLS-1$
fOtpHome.setText(""); //$NON-NLS-1$
fCodePath.setElements(new ArrayList<String>());
fArgs.setText(""); //$NON-NLS-1$
} else {
fName.setText(fEditedRuntime.getName());
fOtpHome.setText(fEditedRuntime.getOtpHome());
fCodePath.setElements(fEditedRuntime.getCodePath());
fArgs.setText(fEditedRuntime.getArgs());
}
setNameStatus(validateName());
// setNodeNameStatus(validateNodeName());
setLocationStatus(validateLocation());
updateStatusLine();
}
protected IStatus validateName() {
final StatusInfo status = new StatusInfo();
final String name = fName.getText();
if (name == null || name.trim().length() == 0) {
status.setError("Enter the runtime's name"); //$NON-NLS-1$
} else {
if (fRequestor.isDuplicateName(name) && (fEditedRuntime == null
|| !name.equals(fEditedRuntime.getName()))) {
status.setError("The name is already used"); //$NON-NLS-1$
} else {
final IStatus s = ResourcesPlugin.getWorkspace().validateName(name,
IResource.FILE);
if (!s.isOK()) {
status.setError(MessageFormat.format("Name is invalid: %s",
(Object[]) new String[] { s.getMessage() }));
}
}
}
return status;
}
protected IStatus validateLocation() {
final StatusInfo status = new StatusInfo();
final String loc = fOtpHome.getText();
if (loc == null || loc.trim().length() == 0) {
status.setInfo("Enter the installation's location");
} else {
final File f = new File(loc);
if (!f.exists()) {
status.setError("Location doesn't exist");
} else if (!f.isDirectory()) {
status.setError("Location isn't a directory");
} else if (!RuntimeInfo.validateLocation(loc)) {
status.setError("Location is not a valid OTP home");
}
}
return status;
}
protected void updateStatusLine() {
IStatus max = null;
for (final IStatus curr : fStatuses) {
if (curr.matches(IStatus.ERROR)) {
updateStatus(curr);
return;
}
if (max == null || curr.getSeverity() > max.getSeverity()) {
max = curr;
}
}
updateStatus(max);
}
@Override
protected void okPressed() {
doOkPressed();
super.okPressed();
}
private void doOkPressed() {
final RuntimeInfo info = new RuntimeInfo(fName.getText().trim(),
fOtpHome.getText().trim(), fArgs.getText().trim(),
fCodePath.getElements());
fRequestor.itemAdded(info);
}
protected void setNameStatus(final IStatus status) {
fStatuses[0] = status;
}
protected void setNodeNameStatus(final IStatus status) {
fStatuses[1] = status;
}
protected void setLocationStatus(final IStatus status) {
fStatuses[2] = status;
}
/**
* Updates the status of the ok button to reflect the given status.
* Subclasses may override this method to update additional buttons.
*
* @param status
* the status.
*/
@Override
protected void updateButtonsEnableState(final IStatus status) {
final Button ok = getButton(IDialogConstants.OK_ID);
if (ok != null && !ok.isDisposed()) {
ok.setEnabled(status.getSeverity() == IStatus.OK);
}
}
/**
* @see org.eclipse.jface.dialogs.Dialog#setButtonLayoutData(org.eclipse.swt.widgets.Button)
*/
@Override
protected void setButtonLayoutData(final Button button) {
super.setButtonLayoutData(button);
}
/**
* Returns the name of the section that this dialog stores its settings in
*
* @return String
*/
protected String getDialogSettingsSectionName() {
return "ADD_VM_DIALOG_SECTION"; //$NON-NLS-1$
}
@Override
public boolean close() {
// DialogSettingsHelper.persistShellGeometry(getShell(),
// getDialogSettingsSectionName());
return super.close();
}
@Override
protected Point getInitialLocation(final Point initialSize) {
// Point initialLocation = DialogSettingsHelper
// .getInitialLocation(getDialogSettingsSectionName());
// if (initialLocation != null)
// {
// return initialLocation;
// }
return super.getInitialLocation(initialSize);
}
@Override
protected Point getInitialSize() {
final Point size = super.getInitialSize();
return size;
// return DialogSettingsHelper.getInitialSize(
// getDialogSettingsSectionName(), size);
}
@Override
public void customButtonPressed(final ListDialogField<String> field,
final int index) {
switch (index) {
case 0:
addPath(field);
break;
case 1:
removePath(field);
break;
case 2:
moveUp(field);
break;
case 3:
moveDown(field);
break;
default:
}
}
private void moveDown(final ListDialogField<String> field) {
final List<String> sel = field.getSelectedElements();
if (sel.size() == 1) {
final String value = sel.get(0);
final int pos = field.getIndexOfElement(value);
if (pos < field.getSize() - 1) {
field.removeElement(value);
field.addElement(value, pos + 1);
}
field.selectElements(new StructuredSelection(value));
field.refresh();
}
}
private void moveUp(final ListDialogField<String> field) {
final List<String> sel = field.getSelectedElements();
if (sel.size() == 1) {
final String value = sel.get(0);
final int pos = field.getIndexOfElement(value);
if (pos > 0) {
field.removeElement(value);
field.addElement(value, pos - 1);
}
field.selectElements(new StructuredSelection(value));
field.refresh();
}
}
private void removePath(final ListDialogField<String> field) {
final List<String> sel = field.getSelectedElements();
field.removeElements(sel);
}
private void addPath(final ListDialogField<String> field) {
final InputDialog dlg = new InputDialog(new Shell(), "Add path",
"Enter a path to be added to ", "", null);
dlg.setBlockOnOpen(true);
dlg.open();
final String value = dlg.getValue();
if (value != null && value.length() > 0) {
final File f = new File(value);
if (f.exists()) {
field.addElement(value);
}
}
}
@Override
public void doubleClicked(final ListDialogField<String> field) {
}
@Override
public void selectionChanged(final ListDialogField<String> field) {
}
protected void browseForInstallDir() {
final DirectoryDialog dialog = new DirectoryDialog(getShell());
dialog.setFilterPath(fOtpHome.getText());
dialog.setMessage(RuntimePreferenceMessages.addDialog_pickInstallationRoot);
final String newPath = dialog.open();
if (newPath != null) {
fOtpHome.setText(newPath);
final File f = new File(newPath);
if (fName.getText().equals("")) {
fName.setText(f.getName());
}
}
}
}