Add build directory configuration to Eclipse plugin

This commit is contained in:
konsoletyper 2014-09-14 21:31:28 +04:00
parent 8202faca69
commit b6a2c62345
6 changed files with 290 additions and 91 deletions

View File

@ -18,7 +18,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.8.0,4.0)",
org.eclipse.ui.editors;bundle-version="[3.8.0,4.0.0)",
org.eclipse.ui.ide;bundle-version="[3.8.2,4.0.0)",
org.eclipse.jdt.ui;bundle-version="[3.8.2,4.0.0)",
org.eclipse.core.filesystem;bundle-version="[1.3.200,1.5.0)"
org.eclipse.core.filesystem;bundle-version="[1.3.200,1.5.0)",
org.eclipse.core.variables;bundle-version="[3.2.600,3.3)"
Bundle-ClassPath: .,
lib/asm-5.0.1.jar,
lib/asm-commons-5.0.1.jar,

View File

@ -0,0 +1,64 @@
package org.teavm.eclipse;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.variables.VariablesPlugin;
import org.osgi.service.prefs.BackingStoreException;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSettings {
public static final String MAIN_CLASS = "mainClass";
public static final String TARGET_DIRECTORY = "targetDirectory";
private IEclipsePreferences preferences;
private String projectName;
public PreferencesBasedTeaVMProjectSettings(IProject project) {
ProjectScope scope = new ProjectScope(project);
preferences = scope.getNode(TeaVMEclipsePlugin.ID);
projectName = project.getName();
}
@Override
public String getMainClass() {
return preferences.get(MAIN_CLASS, "");
}
@Override
public void setMainClass(String mainClass) {
preferences.put(MAIN_CLASS, mainClass);
}
@Override
public String getTargetDirectory() {
return preferences.get(TARGET_DIRECTORY, VariablesPlugin.getDefault().getStringVariableManager()
.generateVariableExpression("workspace_loc", projectName));
}
@Override
public void setTargetDirectory(String targetDirectory) {
preferences.put(TARGET_DIRECTORY, targetDirectory);
}
@Override
public void save() throws CoreException {
try {
preferences.flush();
} catch (BackingStoreException e) {
throw new CoreException(TeaVMEclipsePlugin.makeError(e));
}
}
@Override
public void load() throws CoreException {
try {
preferences.sync();
} catch (BackingStoreException e) {
throw new CoreException(TeaVMEclipsePlugin.makeError(e));
}
}
}

View File

@ -15,8 +15,18 @@
*/
package org.teavm.eclipse;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.ui.plugin.AbstractUIPlugin;
/**
@ -28,6 +38,7 @@ public class TeaVMEclipsePlugin extends AbstractUIPlugin {
public static final String NATURE_ID = ID + ".nature";
public static final String MAIN_METHOD_DIALOG_ID = ID + ".dialogs.mainMethod";
private static TeaVMEclipsePlugin defaultInstance;
private ConcurrentMap<IProject, TeaVMProjectSettings> settingsMap = new ConcurrentHashMap<>();
public TeaVMEclipsePlugin() {
defaultInstance = this;
@ -44,4 +55,78 @@ public class TeaVMEclipsePlugin extends AbstractUIPlugin {
public static void logError(Throwable e) {
getDefault().getLog().log(makeError(e));
}
public TeaVMProjectSettings getSettings(IProject project) {
TeaVMProjectSettings settings = settingsMap.get(project);
if (settings == null) {
settings = new PreferencesBasedTeaVMProjectSettings(project);
settingsMap.putIfAbsent(project, settings);
settings = settingsMap.get(project);
}
return settings;
}
public IStatus addNature(IRunnableContext runnableContext, final IProject project) {
try {
runnableContext.run(false, true, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
addNature(monitor, project);
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
});
return Status.OK_STATUS;
} catch (InterruptedException e) {
return makeError(e);
} catch (InvocationTargetException e) {
return Status.CANCEL_STATUS;
}
}
public void addNature(IProgressMonitor progressMonitor, IProject project) throws CoreException {
IProjectDescription projectDescription = project.getDescription();
String[] natureIds = projectDescription.getNatureIds();
natureIds = Arrays.copyOf(natureIds, natureIds.length + 1);
natureIds[natureIds.length - 1] = TeaVMEclipsePlugin.NATURE_ID;
projectDescription.setNatureIds(natureIds);
project.setDescription(projectDescription, progressMonitor);
}
public IStatus removeNature(IRunnableContext runnableContext, final IProject project) {
try {
runnableContext.run(false, true, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
removeNature(monitor, project);
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
});
return Status.OK_STATUS;
} catch (InterruptedException e) {
return makeError(e);
} catch (InvocationTargetException e) {
return Status.CANCEL_STATUS;
}
}
public void removeNature(IProgressMonitor progressMonitor, IProject project) throws CoreException {
IProjectDescription projectDescription = project.getDescription();
String[] natureIds = projectDescription.getNatureIds();
String[] newNatureIds = new String[natureIds.length - 1];
for (int i = 0; i < natureIds.length; ++i) {
if (natureIds[i].equals(TeaVMEclipsePlugin.NATURE_ID)) {
System.arraycopy(natureIds, 0, newNatureIds, 0, i);
System.arraycopy(natureIds, i + 1, newNatureIds, i, newNatureIds.length - i);
projectDescription.setNatureIds(newNatureIds);
project.setDescription(projectDescription, progressMonitor);
break;
}
}
}
}

View File

@ -28,4 +28,8 @@ public class TeaVMProjectNature implements IProjectNature {
public void setProject(IProject project) {
this.project = project;
}
public TeaVMProjectSettings getSettings() {
return TeaVMEclipsePlugin.getDefault().getSettings(project);
}
}

View File

@ -0,0 +1,21 @@
package org.teavm.eclipse;
import org.eclipse.core.runtime.CoreException;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface TeaVMProjectSettings {
String getMainClass();
void setMainClass(String mainClass);
String getTargetDirectory();
void setTargetDirectory(String targetDirectory);
void save() throws CoreException;
void load() throws CoreException;
}

View File

@ -1,31 +1,28 @@
package org.teavm.eclipse.ui;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
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.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.osgi.service.prefs.BackingStoreException;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceComparator;
import org.teavm.eclipse.TeaVMEclipsePlugin;
import org.teavm.eclipse.TeaVMProjectSettings;
/**
*
@ -35,14 +32,17 @@ public class TeaVMProjectPropertyWidget extends Composite {
private Button natureButton;
private Text mainClassField;
private Button mainClassChooseButton;
private Text targetDirectoryField;
private Button targetDirectoryWorkspaceButton;
private Button targetDirectoryFileSystemButton;
private IJavaProject javaProject;
private IRunnableContext runnableContext;
public TeaVMProjectPropertyWidget(Composite parent) {
super(parent, SWT.NONE);
GridLayout layout = new GridLayout(1, false);
layout.verticalSpacing = 12;
layout.marginWidth = 12;
layout.verticalSpacing = 10;
layout.marginWidth = 10;
setLayout(layout);
natureButton = new Button(this, SWT.CHECK);
natureButton.setText("TeaVM build enabled");
@ -59,30 +59,36 @@ public class TeaVMProjectPropertyWidget extends Composite {
private void updateEnabled(boolean enabled) {
mainClassField.setEnabled(enabled);
mainClassChooseButton.setEnabled(enabled);
targetDirectoryField.setEnabled(enabled);
targetDirectoryWorkspaceButton.setEnabled(enabled);
targetDirectoryFileSystemButton.setEnabled(enabled);
}
private void createOptionsContainer() {
Composite container = new Composite(this, SWT.NONE);
container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.verticalSpacing = 6;
layout.horizontalSpacing = 6;
layout.horizontalSpacing = 5;
container.setLayout(layout);
createMainClassField(container);
createTargetDirectoryField(container);
}
private void createMainClassField(Composite container) {
Label label = new Label(container, SWT.NONE);
label.setText("Main class:");
label.setText("&Main class:");
Composite row = new Composite(container, SWT.NONE);
RowLayout rowLayout = new RowLayout();
row.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
GridLayout rowLayout = new GridLayout();
rowLayout.numColumns = 2;
rowLayout.horizontalSpacing = 2;
row.setLayout(rowLayout);
rowLayout.type = SWT.HORIZONTAL;
rowLayout.spacing = 3;
mainClassField = new Text(row, SWT.SINGLE | SWT.BORDER);
RowData rowData = new RowData();
rowData.width = 300;
mainClassField.setLayoutData(rowData);
mainClassField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
mainClassChooseButton = new Button(row, SWT.PUSH);
mainClassChooseButton.setText("Choose...");
mainClassChooseButton.addSelectionListener(new SelectionAdapter() {
@ -92,6 +98,44 @@ public class TeaVMProjectPropertyWidget extends Composite {
});
}
private void createTargetDirectoryField(Composite container) {
Label label = new Label(container, SWT.NONE);
label.setText("&Target directory:");
Composite row = new Composite(container, SWT.NONE);
row.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
GridLayout rowLayout = new GridLayout();
rowLayout.numColumns = 3;
rowLayout.horizontalSpacing = 2;
row.setLayout(rowLayout);
targetDirectoryField = new Text(row, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
targetDirectoryField.setData(new GridData(SWT.FILL, SWT.CENTER, true, false));
targetDirectoryWorkspaceButton = new Button(row, SWT.PUSH);
targetDirectoryWorkspaceButton.setText("Workspace...");
targetDirectoryWorkspaceButton.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
chooseWorkspaceTargetDirectory();
}
});
targetDirectoryFileSystemButton = new Button(row, SWT.PUSH);
targetDirectoryFileSystemButton.setText("External...");
targetDirectoryFileSystemButton.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
chooseFileSystemTargetDirectory();
}
});
}
public void setJavaProject(IJavaProject javaProject) {
this.javaProject = javaProject;
}
public void setRunnableContext(IRunnableContext runnableContext) {
this.runnableContext = runnableContext;
}
private void chooseMainClass() {
MainClassSelectionDialog selectionDialog = new MainClassSelectionDialog(getShell(), javaProject);
if (selectionDialog.open() == MainClassSelectionDialog.OK) {
@ -103,23 +147,42 @@ public class TeaVMProjectPropertyWidget extends Composite {
}
}
public void setJavaProject(IJavaProject javaProject) {
this.javaProject = javaProject;
private void chooseWorkspaceTargetDirectory() {
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), new WorkbenchLabelProvider(),
new WorkbenchContentProvider());
dialog.setTitle("Selecting target directory");
dialog.setMessage("Please, select a target directory for TeaVM build");
dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
dialog.setComparator(new ResourceComparator(ResourceComparator.NAME));
if (dialog.open() == IDialogConstants.OK_ID) {
IResource resource = (IResource)dialog.getFirstResult();
if (resource != null) {
String path = resource.getFullPath().toString();
String fileLoc = VariablesPlugin.getDefault().getStringVariableManager()
.generateVariableExpression("workspace_loc", path);
targetDirectoryField.setText(fileLoc);
}
}
}
public void setRunnableContext(IRunnableContext runnableContext) {
this.runnableContext = runnableContext;
private void chooseFileSystemTargetDirectory() {
String filePath = targetDirectoryField.getText();
FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
filePath = dialog.open();
if (filePath != null) {
targetDirectoryField.setText(filePath);
}
}
public void load(IProject project) {
try {
natureButton.setSelection(project.hasNature(TeaVMEclipsePlugin.NATURE_ID));
ProjectScope scope = new ProjectScope(project);
IEclipsePreferences preferences = scope.getNode(TeaVMEclipsePlugin.ID);
preferences.sync();
mainClassField.setText(preferences.get("mainClass", ""));
TeaVMProjectSettings settings = TeaVMEclipsePlugin.getDefault().getSettings(project);
settings.load();
mainClassField.setText(settings.getMainClass());
targetDirectoryField.setText(settings.getTargetDirectory());
updateEnabled(natureButton.getSelection());
} catch (CoreException | BackingStoreException e) {
} catch (CoreException e) {
reportError(e);
}
}
@ -135,74 +198,35 @@ public class TeaVMProjectPropertyWidget extends Composite {
removeNature(project);
}
}
ProjectScope scope = new ProjectScope(project);
IEclipsePreferences preferences = scope.getNode(TeaVMEclipsePlugin.ID);
preferences.put("mainClass", mainClassField.getText().trim());
preferences.flush();
TeaVMProjectSettings settings = TeaVMEclipsePlugin.getDefault().getSettings(project);
settings.setMainClass(mainClassField.getText().trim());
settings.setTargetDirectory(targetDirectoryField.getText());
settings.save();
return true;
} catch (CoreException | BackingStoreException e) {
} catch (CoreException e) {
reportError(e);
return false;
}
}
private void addNature(final IProject project) {
try {
runnableContext.run(false, true, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
IProjectDescription projectDescription = project.getDescription();
String[] natureIds = projectDescription.getNatureIds();
natureIds = Arrays.copyOf(natureIds, natureIds.length + 1);
natureIds[natureIds.length - 1] = TeaVMEclipsePlugin.NATURE_ID;
projectDescription.setNatureIds(natureIds);
project.setDescription(projectDescription, monitor);
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
});
} catch (InterruptedException e) {
reportError(e);
} catch (InvocationTargetException e) {
return;
}
reportStatus(TeaVMEclipsePlugin.getDefault().addNature(runnableContext, project));
}
private void removeNature(final IProject project) {
try {
runnableContext.run(false, true, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
IProjectDescription projectDescription = project.getDescription();
String[] natureIds = projectDescription.getNatureIds();
String[] newNatureIds = new String[natureIds.length - 1];
for (int i = 0; i < natureIds.length; ++i) {
if (natureIds[i].equals(TeaVMEclipsePlugin.NATURE_ID)) {
System.arraycopy(natureIds, 0, newNatureIds, 0, i);
System.arraycopy(natureIds, i + 1, newNatureIds, i, newNatureIds.length - i);
projectDescription.setNatureIds(newNatureIds);
project.setDescription(projectDescription, monitor);
break;
}
}
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
});
} catch (InterruptedException e) {
reportError(e);
} catch (InvocationTargetException e) {
return;
}
reportStatus(TeaVMEclipsePlugin.getDefault().removeNature(runnableContext, project));
}
private void reportError(Throwable e) {
IStatus status = TeaVMEclipsePlugin.makeError(e);
TeaVMEclipsePlugin.getDefault().getLog().log(status);
ErrorDialog.openError(getShell(), "Error occured", "Error occured", status);
reportStatus(TeaVMEclipsePlugin.makeError(e));
}
private void reportStatus(IStatus status) {
if (!status.isOK()) {
TeaVMEclipsePlugin.getDefault().getLog().log(status);
}
if (status.getSeverity() == IStatus.ERROR) {
ErrorDialog.openError(getShell(), "Error occured", "Error occured", status);
}
}
}