/*******************************************************************************
* Copyright (c) 2012 Sierra Wireless 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:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.koneki.ldt.debug.ui.internal.interpreters;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.dltk.core.environment.IEnvironment;
import org.eclipse.dltk.core.internal.environment.LazyFileHandle;
import org.eclipse.dltk.internal.debug.ui.interpreters.AbstractInterpreterLibraryBlock;
import org.eclipse.dltk.internal.debug.ui.interpreters.AddScriptInterpreterDialog;
import org.eclipse.dltk.internal.debug.ui.interpreters.IAddInterpreterDialogRequestor;
import org.eclipse.dltk.internal.debug.ui.interpreters.IScriptInterpreterDialog;
import org.eclipse.dltk.internal.debug.ui.interpreters.InterpretersMessages;
import org.eclipse.dltk.launching.EnvironmentVariable;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.dltk.launching.IInterpreterInstallType;
import org.eclipse.dltk.launching.InterpreterStandin;
import org.eclipse.dltk.ui.environment.IEnvironmentUI;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.koneki.ldt.debug.core.IEmbeddedInterpreterInstallType;
import org.eclipse.koneki.ldt.debug.core.internal.interpreter.generic.LuaGenericInterpreterInstallType;
import org.eclipse.koneki.ldt.debug.core.internal.interpreter.generic.LuaGenericInterpreterUtil;
import org.eclipse.koneki.ldt.debug.core.internal.model.interpreter.Info;
import org.eclipse.koneki.ldt.debug.core.internal.model.interpreter.InterpreterFactory;
import org.eclipse.koneki.ldt.debug.core.internal.model.interpreter.impl.InterpreterFactoryImpl;
import org.eclipse.koneki.ldt.debug.core.internal.model.interpreter.impl.InterpreterPackageImpl;
import org.eclipse.koneki.ldt.debug.ui.internal.Activator;
import org.eclipse.koneki.ldt.ui.SWTUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
@SuppressWarnings("restriction")
public class AddLuaInterpreterDialog extends StatusDialog implements IScriptInterpreterDialog {
private IAddInterpreterDialogRequestor requestor;
private IEnvironment environment;
private IInterpreterInstall currentInterperter;
private IInterpreterInstallType[] interpreterInstallTypes;
// UI components
private ComboViewer typesCombo;
private Text nameText;
private Text pathText;
private Button browseButton;
private Text argsText;
private LuaInterpreterEnvironmentVariablesBlock environementVariableBlock;
private Button handlesExecutionOption;
private Group capabilitiesGroup;
private Label capabilitiesDesctiptionLabel;
private Button handlesFilesAsArguments;
public AddLuaInterpreterDialog(final IAddInterpreterDialogRequestor requestor, final Shell shell, final IEnvironment environment,
final IInterpreterInstallType[] interpreterInstallTypes, final IInterpreterInstall standin) {
super(shell);
this.requestor = requestor;
this.environment = environment;
this.currentInterperter = standin;
this.interpreterInstallTypes = interpreterInstallTypes;
}
@Override
protected boolean isResizable() {
return true;
}
@Override
protected Control createDialogArea(final Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
Point margin = new Point(0, 0);
margin.x = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
margin.y = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
Point spacing = new Point(0, 0);
spacing.x = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
spacing.y = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
GridLayoutFactory.swtDefaults().spacing(spacing).margins(margin).numColumns(3).applyTo(container);
GridDataFactory.swtDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(container);
createLabel(container, InterpretersMessages.addInterpreterDialog_InterpreterEnvironmentType);
typesCombo = new ComboViewer(container);
GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).span(2, 1).applyTo(typesCombo.getControl());
createLabel(container, InterpretersMessages.addInterpreterDialog_InterpreterExecutableName);
pathText = new Text(container, SWT.SINGLE | SWT.BORDER);
GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).hint(300, SWT.DEFAULT).applyTo(pathText);
browseButton = new Button(container, SWT.PUSH);
browseButton.setText(InterpretersMessages.addInterpreterDialog_browse1);
GridDataFactory.swtDefaults().hint(SWTUtil.getButtonWidthHint(browseButton), -1).applyTo(browseButton);
createLabel(container, InterpretersMessages.addInterpreterDialog_InterpreterEnvironmentName);
nameText = new Text(container, SWT.SINGLE | SWT.BORDER);
GridDataFactory.swtDefaults().grab(true, false).span(2, 1).align(SWT.FILL, SWT.CENTER).applyTo(nameText);
createLabel(container, InterpretersMessages.AddInterpreterDialog_iArgs);
argsText = new Text(container, SWT.SINGLE | SWT.BORDER);
GridDataFactory.swtDefaults().grab(true, false).span(2, 1).align(SWT.FILL, SWT.CENTER).applyTo(argsText);
environementVariableBlock = new LuaInterpreterEnvironmentVariablesBlock(new AddInterpreterDialogAdapter(requestor, getShell(),
interpreterInstallTypes, currentInterperter));
final Composite environmentComposite = (Composite) environementVariableBlock.createControl(container);
GridLayoutFactory.swtDefaults().margins(0, 0).numColumns(2).applyTo(environmentComposite);
GridDataFactory.swtDefaults().grab(true, true).span(3, 1).align(SWT.FILL, SWT.FILL).applyTo(environmentComposite);
// Interpreter Capabilities
capabilitiesGroup = new Group(container, SWT.None);
capabilitiesGroup.setText(Messages.AddLuaInterpreterDialog_CapabilitesGroupLabel);
GridLayoutFactory.swtDefaults().margins(0, 0).numColumns(1).applyTo(capabilitiesGroup);
GridDataFactory.swtDefaults().grab(true, false).span(3, 1).align(SWT.FILL, SWT.FILL).applyTo(capabilitiesGroup);
capabilitiesDesctiptionLabel = new Label(capabilitiesGroup, SWT.NONE);
toItalic(capabilitiesDesctiptionLabel);
GridDataFactory.swtDefaults().span(3, 1).grab(true, false).align(SWT.FILL, SWT.FILL).applyTo(capabilitiesDesctiptionLabel);
handlesExecutionOption = new Button(capabilitiesGroup, SWT.CHECK);
handlesExecutionOption.setText(Messages.AddLuaInterpreterDialog_ExecutionOption);
handlesFilesAsArguments = new Button(capabilitiesGroup, SWT.CHECK);
handlesFilesAsArguments.setText(Messages.AddLuaInterpreterDialog_FilesAsArguments);
applyDialogFont(container);
hookListeners();
init();
return container;
}
private <T extends Control> T toItalic(final T control) {
final FontRegistry fontRegistry = JFaceResources.getFontRegistry();
for (final FontData fontData : control.getFont().getFontData()) {
final Font font = fontRegistry.getItalic(fontData.getName());
control.setFont(font);
}
return control;
}
private Label createLabel(final Composite container, final String text) {
final Label label = new Label(container, SWT.NONE);
label.setText(text);
GridDataFactory.swtDefaults().applyTo(label);
return label;
}
private void hookListeners() {
typesCombo.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
updateOnInterpreterTypeChange();
}
});
browseButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
widgetDefaultSelected(e);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
browseForInstallation();
}
});
pathText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
updateStatusLine();
}
});
nameText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
updateStatusLine();
}
});
}
private void init() {
handlesExecutionOption.setSelection(LuaGenericInterpreterUtil.interpreterHandlesExecuteOption(currentInterperter));
handlesFilesAsArguments.setSelection(LuaGenericInterpreterUtil.interpreterHandlesFilesAsArgument(currentInterperter));
// init type combo
typesCombo.setContentProvider(new ArrayContentProvider());
typesCombo.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
if (element instanceof IInterpreterInstallType) {
return ((IInterpreterInstallType) element).getName();
}
return super.getText(element);
}
});
typesCombo.setInput(interpreterInstallTypes);
typesCombo.getControl().setEnabled(currentInterperter == null);
// init field values
if (currentInterperter != null) {
typesCombo.setSelection(new StructuredSelection(currentInterperter.getInterpreterInstallType()));
updateOnInterpreterTypeChange();
if (currentInterperter.getInstallLocation().length() > 0)
pathText.setText(currentInterperter.getInstallLocation().toOSString());
nameText.setText(currentInterperter.getName());
String args = currentInterperter.getInterpreterArgs();
if (args != null)
argsText.setText(args);
environementVariableBlock.initializeFrom(currentInterperter, currentInterperter.getInterpreterInstallType());
} else {
// for user experience, the selected type by default should be Lua Generic
for (IInterpreterInstallType type : interpreterInstallTypes) {
if (type instanceof LuaGenericInterpreterInstallType && typesCombo.getSelection().isEmpty())
typesCombo.setSelection(new StructuredSelection(type));
}
}
// update environment block buttons
environementVariableBlock.update();
}
/** Disables all {@link Control}s from {@link #capabilitiesGroup} */
private void setCapabilityGroupEnabled(final boolean enabled) {
final Control[] controls = { capabilitiesGroup, handlesExecutionOption, handlesFilesAsArguments };
for (final Control control : controls)
if (control != null)
control.setEnabled(enabled);
if (enabled)
capabilitiesDesctiptionLabel.setText(Messages.AddLuaInterpreterDialog_WhatAreCapabilitiesLabel);
else
capabilitiesDesctiptionLabel.setText(Messages.AddLuaInterpreterDialog_InterpreterNotConfigurable);
}
private void updateOnInterpreterTypeChange() {
final IInterpreterInstallType selectedType = getSelectedInterpreterType();
final boolean isEmbedded = selectedType instanceof IEmbeddedInterpreterInstallType;
browseButton.setEnabled(!isEmbedded);
pathText.setEnabled(!isEmbedded);
setCapabilityGroupEnabled(!isEmbedded);
// Set path text as Embedded because we are unable to retrieve the default path of the embedded interpreter type
final String embeddedPathValue = "(Embedded)"; //$NON-NLS-1$
if (isEmbedded) {
pathText.setText(embeddedPathValue);
} else if (embeddedPathValue.equals(pathText.getText())) {
pathText.setText(""); //$NON-NLS-1$
} else if (currentInterperter != null) {
pathText.setText(currentInterperter.getInstallLocation().toOSString());
}
}
private IInterpreterInstallType getSelectedInterpreterType() {
return (IInterpreterInstallType) ((IStructuredSelection) typesCombo.getSelection()).getFirstElement();
}
private void browseForInstallation() {
IEnvironmentUI environmentUI = (IEnvironmentUI) environment.getAdapter(IEnvironmentUI.class);
if (environmentUI != null) {
String defaultPath = currentInterperter != null ? currentInterperter.getInstallLocation().toOSString() : null;
String newPath = environmentUI.selectFile(getShell(), IEnvironmentUI.EXECUTABLE, defaultPath);
if (newPath != null) {
pathText.setText(newPath);
}
}
}
@Override
protected void okPressed() {
if (currentInterperter == null) {
IInterpreterInstallType selectedType = getSelectedInterpreterType();
currentInterperter = new InterpreterStandin(selectedType, createUniqueId(selectedType));
// notify the preference page of the new interpreter, the interpreter have to be filled
setFieldValuesToInterpreter();
requestor.interpreterAdded(currentInterperter);
} else {
setFieldValuesToInterpreter();
}
super.okPressed();
}
private String createUniqueId(IInterpreterInstallType interpreterType) {
String id = null;
do {
id = String.valueOf(System.currentTimeMillis());
} while (interpreterType.findInterpreterInstall(id) != null);
return id;
}
protected void setFieldValuesToInterpreter() {
currentInterperter.setInstallLocation(new LazyFileHandle(environment.getId(), new Path(pathText.getText().trim())));
currentInterperter.setName(nameText.getText().trim());
final String argString = argsText.getText().trim();
if (argString != null && argString.length() > 0) {
currentInterperter.setInterpreterArgs(argString);
} else {
currentInterperter.setInterpreterArgs(null);
}
/*
* Update interpreter capabilities
*/
// Execution option
final boolean executionOptionChecked = handlesExecutionOption != null && handlesExecutionOption.getSelection();
// Files as argument option
final boolean filesAsArgumentOptionChecked = handlesFilesAsArguments != null && handlesFilesAsArguments.getSelection();
final InterpreterFactory factory = InterpreterFactoryImpl.eINSTANCE;
final Info info = factory.createInfo();
info.setExecuteOptionCapable(executionOptionChecked);
info.setFileAsArgumentsCapable(filesAsArgumentOptionChecked);
currentInterperter.replaceExtension(InterpreterPackageImpl.eINSTANCE.getInfo(), info);
environementVariableBlock.performApply(currentInterperter);
}
@Override
public boolean execute() {
return open() == Window.OK;
}
@Override
public void updateStatusLine() {
String path = pathText.getText().trim();
if (path.isEmpty()) {
updateStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, InterpretersMessages.addInterpreterDialog_enterLocation));
} else {
String name = nameText.getText().trim();
if (name.isEmpty()) {
updateStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, InterpretersMessages.addInterpreterDialog_enterName));
} else if (requestor.isDuplicateName(name, currentInterperter)) {
updateStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, InterpretersMessages.addInterpreterDialog_duplicateName));
} else {
updateStatus(Status.OK_STATUS);
}
}
}
/**
* This method is override just to fix a scope problem between IStatus and Dialog super class
*/
@Override
public void setButtonLayoutData(Button button) {
super.setButtonLayoutData(button);
}
/**
* Adapter for the Environment Variable Block The block doesn't take a IAddScriptInterpreter dialog but a AddScriptInterpreterDialog
*/
private class AddInterpreterDialogAdapter extends AddScriptInterpreterDialog {
public AddInterpreterDialogAdapter(IAddInterpreterDialogRequestor requestor, Shell shell, IInterpreterInstallType[] interpreterInstallTypes,
IInterpreterInstall editedInterpreter) {
super(requestor, shell, interpreterInstallTypes, editedInterpreter);
}
@Override
protected AbstractInterpreterLibraryBlock createLibraryBlock(AddScriptInterpreterDialog dialog) {
return null;
}
@Override
public IEnvironment getEnvironment() {
return environment;
}
@Override
public void updateLibraries(EnvironmentVariable[] newVars, EnvironmentVariable[] oldVars) {
}
@Override
protected void updateValidateInterpreterLocation() {
}
@Override
public Shell getShell() {
return AddLuaInterpreterDialog.this.getShell();
}
@Override
public void updateStatusLine() {
AddLuaInterpreterDialog.this.updateStatusLine();
}
@Override
public void setSystemLibraryStatus(IStatus status) {
}
@Override
public void setButtonLayoutData(Button button) {
AddLuaInterpreterDialog.this.setButtonLayoutData(button);
}
@Override
public int open() {
return OK;
}
}
}