diff --git a/teavm-eclipse/teavm-eclipse-plugin/META-INF/MANIFEST.MF b/teavm-eclipse/teavm-eclipse-plugin/META-INF/MANIFEST.MF index 4616fadfd..4ca24ca16 100644 --- a/teavm-eclipse/teavm-eclipse-plugin/META-INF/MANIFEST.MF +++ b/teavm-eclipse/teavm-eclipse-plugin/META-INF/MANIFEST.MF @@ -18,8 +18,10 @@ 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.variables;bundle-version="[3.2.600,3.3)" + org.eclipse.core.filesystem;bundle-version="[1.3.200,2)", + org.eclipse.core.variables;bundle-version="[3.2.600,4)", + org.eclipse.core.databinding.observable;bundle-version="[1.4.1,2)", + org.eclipse.jface.databinding;bundle-version="[1.6.0,2)" Bundle-ClassPath: ., lib/asm-5.0.1.jar, lib/asm-commons-5.0.1.jar, diff --git a/teavm-eclipse/teavm-eclipse-plugin/plugin.xml b/teavm-eclipse/teavm-eclipse-plugin/plugin.xml index 71240220b..d09cc3412 100644 --- a/teavm-eclipse/teavm-eclipse-plugin/plugin.xml +++ b/teavm-eclipse/teavm-eclipse-plugin/plugin.xml @@ -64,7 +64,7 @@ - + diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/PreferencesBasedTeaVMProjectSettings.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/PreferencesBasedTeaVMProjectSettings.java index 73711bfd0..585949f8c 100644 --- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/PreferencesBasedTeaVMProjectSettings.java +++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/PreferencesBasedTeaVMProjectSettings.java @@ -19,6 +19,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting public static final String MAIN_CLASS = "mainClass"; public static final String TARGET_DIRECTORY = "targetDirectory"; public static final String TARGET_FILE_NAME = "targetFileName"; + public static final String RUNTIME = "runtime"; public static final String MINIFYING = "minifying"; public static final String INCREMENTAL = "incremental"; public static final String CACHE_DIRECTORY = "cacheDirectory"; @@ -135,6 +136,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting private String targetDirectory; private String targetFileName; private boolean minifying; + private TeaVMRuntimeMode runtimeMode = TeaVMRuntimeMode.SEPARATE; private boolean incremental; private String cacheDirectory; private boolean sourceMapsGenerated; @@ -207,6 +209,16 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting this.minifying = minifying; } + @Override + public TeaVMRuntimeMode getRuntimeMode() { + return runtimeMode; + } + + @Override + public void setRuntimeMode(TeaVMRuntimeMode runtimeMode) { + this.runtimeMode = runtimeMode; + } + @Override public boolean isIncremental() { return incremental; @@ -249,12 +261,15 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting @Override public Properties getProperties() { - return new Properties(properties); + Properties copy = new Properties(); + copy.putAll(properties); + return copy; } @Override public void setProperties(Properties properties) { - this.properties = new Properties(properties); + this.properties = new Properties(); + this.properties.putAll(properties); } public void load() throws BackingStoreException { @@ -264,6 +279,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting targetDirectory = preferences.get(TARGET_DIRECTORY, ""); targetFileName = preferences.get(TARGET_FILE_NAME, ""); minifying = preferences.getBoolean(MINIFYING, true); + runtimeMode = TeaVMRuntimeMode.valueOf(preferences.get(RUNTIME, TeaVMRuntimeMode.SEPARATE.name())); incremental = preferences.getBoolean(INCREMENTAL, false); cacheDirectory = preferences.get(CACHE_DIRECTORY, ""); sourceMapsGenerated = preferences.getBoolean(SOURCE_MAPS, true); @@ -283,6 +299,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting preferences.put(TARGET_DIRECTORY, targetDirectory); preferences.put(TARGET_FILE_NAME, targetFileName); preferences.putBoolean(MINIFYING, minifying); + preferences.put(RUNTIME, runtimeMode.name()); preferences.putBoolean(INCREMENTAL, incremental); preferences.put(CACHE_DIRECTORY, cacheDirectory); preferences.putBoolean(SOURCE_MAPS, sourceMapsGenerated); diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMEclipseProgressListener.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMEclipseProgressListener.java index 05ee3be50..6a365594c 100644 --- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMEclipseProgressListener.java +++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMEclipseProgressListener.java @@ -10,7 +10,7 @@ import org.teavm.vm.TeaVMProgressListener; * @author Alexey Andreev */ class TeaVMEclipseProgressListener implements TeaVMProgressListener { - private TeaVMBuilder builder; + private TeaVMProjectBuilder builder; private IProgressMonitor progressMonitor; private TeaVMPhase currentPhase; private int currentProgress; @@ -18,7 +18,7 @@ class TeaVMEclipseProgressListener implements TeaVMProgressListener { private int total; private int last; - public TeaVMEclipseProgressListener(TeaVMBuilder builder, IProgressMonitor progressMonitor, int total) { + public TeaVMEclipseProgressListener(TeaVMProjectBuilder builder, IProgressMonitor progressMonitor, int total) { this.builder = builder; this.progressMonitor = progressMonitor; this.total = total; diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProfile.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProfile.java index b87ea810a..e25141922 100644 --- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProfile.java +++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProfile.java @@ -31,6 +31,10 @@ public interface TeaVMProfile { void setMinifying(boolean minifying); + TeaVMRuntimeMode getRuntimeMode(); + + void setRuntimeMode(TeaVMRuntimeMode runtimeMode); + boolean isIncremental(); void setIncremental(boolean incremental); diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMBuilder.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java similarity index 97% rename from teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMBuilder.java rename to teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java index 63f33bd08..a9c5530db 100644 --- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMBuilder.java +++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java @@ -24,7 +24,7 @@ import org.teavm.tooling.TeaVMToolException; * * @author Alexey Andreev */ -public class TeaVMBuilder extends IncrementalProjectBuilder { +public class TeaVMProjectBuilder extends IncrementalProjectBuilder { private static final int TICKS_PER_PROFILE = 10000; private URL[] classPath; private IContainer[] sourceContainers; @@ -39,7 +39,7 @@ public class TeaVMBuilder extends IncrementalProjectBuilder { monitor.beginTask("Running TeaVM", profiles.length * TICKS_PER_PROFILE); try { prepareClassPath(); - ClassLoader classLoader = new URLClassLoader(classPath, TeaVMBuilder.class.getClassLoader()); + ClassLoader classLoader = new URLClassLoader(classPath, TeaVMProjectBuilder.class.getClassLoader()); for (TeaVMProfile profile : profiles) { SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, TICKS_PER_PROFILE); buildProfile(kind, subMonitor, profile, classLoader); @@ -80,8 +80,8 @@ public class TeaVMBuilder extends IncrementalProjectBuilder { String targetDir = profile.getTargetDirectory(); tool.setTargetDirectory(new File(varManager.performStringSubstitution(targetDir))); tool.setTargetFileName(profile.getTargetFileName()); - tool.setRuntime(RuntimeCopyOperation.SEPARATE); tool.setMinifying(profile.isMinifying()); + tool.setRuntime(mapRuntime(profile.getRuntimeMode())); tool.setMainClass(profile.getMainClass()); tool.getProperties().putAll(profile.getProperties()); tool.setIncremental(profile.isIncremental()); @@ -105,6 +105,17 @@ public class TeaVMBuilder extends IncrementalProjectBuilder { } } + private RuntimeCopyOperation mapRuntime(TeaVMRuntimeMode runtimeMode) { + switch (runtimeMode) { + case MERGE: + return RuntimeCopyOperation.MERGED; + case SEPARATE: + return RuntimeCopyOperation.SEPARATE; + default: + return RuntimeCopyOperation.NONE; + } + } + private Set classesToResources(Collection classNames) { Set resourcePaths = new HashSet<>(); for (String className : classNames) { diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMRuntimeMode.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMRuntimeMode.java new file mode 100644 index 000000000..45eb51e8d --- /dev/null +++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMRuntimeMode.java @@ -0,0 +1,11 @@ +package org.teavm.eclipse; + +/** + * + * @author Alexey Andreev + */ +public enum TeaVMRuntimeMode { + SEPARATE, + MERGE, + NONE +} diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProfileDialog.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProfileDialog.java index 34d6c4ab7..d8eea2fe3 100644 --- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProfileDialog.java +++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProfileDialog.java @@ -1,5 +1,9 @@ package org.teavm.eclipse.ui; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import org.eclipse.core.databinding.observable.list.WritableList; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; @@ -8,26 +12,48 @@ import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TextCellEditor; 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.widgets.*; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.Text; 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.TeaVMProfile; import org.teavm.eclipse.TeaVMProjectSettings; +import org.teavm.eclipse.TeaVMRuntimeMode; /** * * @author Alexey Andreev */ public class TeaVMProfileDialog extends Dialog { + private static List runtimeModes = Arrays.asList(TeaVMRuntimeMode.SEPARATE, + TeaVMRuntimeMode.MERGE, TeaVMRuntimeMode.NONE); private Text nameField; private Text mainClassField; private Button mainClassChooseButton; @@ -36,6 +62,17 @@ public class TeaVMProfileDialog extends Dialog { private Button targetDirectoryFileSystemButton; private Text targetFileNameField; private Button minifyingButton; + private Combo runtimeField; + private Button incrementalButton; + private Text cacheDirectoryField; + private Button cacheDirectoryWorkspaceButton; + private Button cacheDirectoryFileSystemButton; + private Button debugInformationButton; + private Button sourceMapsButton; + private TableViewer propertiesTableViewer; + private Button addPropertyButton; + private Button deletePropertyButton; + private WritableList propertyList = new WritableList(); private IJavaProject javaProject; private TeaVMProjectSettings settings; private TeaVMProfile profile; @@ -61,43 +98,199 @@ public class TeaVMProfileDialog extends Dialog { @Override protected Control createDialogArea(Composite parent) { Composite area = (Composite)super.createDialogArea(parent); - area.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true)); + area.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + //ScrolledComposite scrollContainer = new ScrolledComposite(area, SWT.V_SCROLL | SWT.H_SCROLL); + //scrollContainer.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true)); Composite container = new Composite(area, SWT.NONE); - container.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true)); - GridLayout layout = new GridLayout(2, false); - layout.horizontalSpacing = 5; + container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + /*scrollContainer.setContent(container); + scrollContainer.setExpandHorizontal(true); + scrollContainer.setExpandVertical(true);*/ + GridLayout layout = new GridLayout(1, false); + layout.marginHeight = 8; + layout.verticalSpacing = 10; container.setLayout(layout); - createNameField(container); - createMainClassField(container); - createTargetDirectoryField(container); - createTargetFileNameField(container); - createMinifyField(container); + createMainGroup(container); + createOutputGroup(container); + createIncrementalGroup(container); + createDebugGroup(container); + createPropertiesGroup(container); load(); + //container.setSize(container.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + //scrollContainer.setMinSize(container.getSize()); + //return scrollContainer; return container; } + private void createMainGroup(Composite parent) { + Group group = createGroup(parent, "Main settings", 3, false); + createNameField(group); + createMainClassField(group); + } + + private void createOutputGroup(Composite parent) { + Group group = createGroup(parent, "Output settings", 4, false); + createTargetDirectoryField(group); + createTargetFileNameField(group); + createRuntimeField(group); + createMinifyField(group); + } + + private void createIncrementalGroup(Composite parent) { + Group group = createGroup(parent, "Incremental build settings", 4, false); + createIncrementalField(group); + createCacheDirectoryField(group); + } + + private void createDebugGroup(Composite parent) { + Group group = createGroup(parent, "Debug settings", 1, false); + createDebugInformationField(group); + createSourceMapsField(group); + } + + private void createPropertiesGroup(Composite parent) { + Group group = createGroup(parent, "Properties", 2, true); + propertiesTableViewer = new TableViewer(group, SWT.BORDER | SWT.V_SCROLL); + propertiesTableViewer.getTable().setLinesVisible(true); + propertiesTableViewer.getTable().setHeaderVisible(true); + propertiesTableViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 3)); + propertiesTableViewer.setContentProvider(new ObservableListContentProvider()); + propertiesTableViewer.setInput(propertyList); + + TableViewerColumn propertyColumn = new TableViewerColumn(propertiesTableViewer, SWT.LEFT); + propertyColumn.getColumn().setWidth(200); + propertyColumn.getColumn().setText("Property"); + propertyColumn.setLabelProvider(new ColumnLabelProvider() { + @Override public String getText(Object element) { + KeyValue item = (KeyValue)element; + return item.key; + } + }); + propertyColumn.setEditingSupport(new KeyValueEditingSupport(propertyColumn.getViewer(), + propertiesTableViewer.getTable()) { + @Override protected Object getValue(Object element) { + KeyValue item = (KeyValue)element; + return item.key; + } + @Override protected void setValue(Object element, Object value) { + KeyValue item = (KeyValue)element; + item.key = (String)value; + getViewer().update(element, null); + } + }); + + TableViewerColumn valueColumn = new TableViewerColumn(propertiesTableViewer, SWT.LEFT); + valueColumn.getColumn().setWidth(200); + valueColumn.getColumn().setText("Value"); + valueColumn.setLabelProvider(new ColumnLabelProvider() { + @Override public String getText(Object element) { + KeyValue item = (KeyValue)element; + return item.value; + } + }); + valueColumn.setEditingSupport(new KeyValueEditingSupport(valueColumn.getViewer(), + propertiesTableViewer.getTable()) { + @Override protected Object getValue(Object element) { + KeyValue item = (KeyValue)element; + return item.value; + } + @Override protected void setValue(Object element, Object value) { + KeyValue item = (KeyValue)element; + item.value = (String)value; + getViewer().update(element, null); + } + }); + + addPropertyButton = new Button(group, SWT.PUSH); + addPropertyButton.setText("Add"); + addPropertyButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); + addPropertyButton.addSelectionListener(new SelectionAdapter() { + @Override public void widgetSelected(SelectionEvent e) { + addProperty(); + } + }); + + deletePropertyButton = new Button(group, SWT.PUSH); + deletePropertyButton.setText("Delete"); + deletePropertyButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); + deletePropertyButton.addSelectionListener(new SelectionAdapter() { + @Override public void widgetSelected(SelectionEvent e) { + deleteProperty(); + } + }); + } + + static abstract class KeyValueEditingSupport extends EditingSupport { + private TextCellEditor editor; + + public KeyValueEditingSupport(ColumnViewer viewer, Table table) { + super(viewer); + editor = new TextCellEditor(table); + } + + @Override + protected CellEditor getCellEditor(Object element) { + return editor; + } + + @Override + protected boolean canEdit(Object element) { + return true; + } + } + + private void addProperty() { + KeyValue item = new KeyValue(); + propertyList.add(item); + } + + private void deleteProperty() { + int index = propertiesTableViewer.getTable().getSelectionIndex(); + if (index < 0) { + return; + } + KeyValue item = (KeyValue)propertyList.get(index); + boolean confirmed = MessageDialog.openConfirm(getShell(), "Property deletion confirmation", + "Are you sure to delete property " + item.key + "?"); + if (!confirmed) { + return; + } + propertyList.remove(index); + } + + static class KeyValue { + String key = ""; + String value = ""; + } + + private Group createGroup(Composite parent, String title, int columns, boolean fillVert) { + Group group = new Group(parent, SWT.NONE); + group.setLayoutData(new GridData(SWT.FILL, fillVert ? SWT.FILL : SWT.TOP, true, fillVert)); + group.setText(title); + GridLayout layout = new GridLayout(columns, false); + layout.horizontalSpacing = 3; + layout.verticalSpacing = 2; + layout.marginWidth = 10; + group.setLayout(layout); + return group; + } + private void createNameField(Composite container) { Label label = new Label(container, SWT.NONE); label.setText("&Name:"); nameField = new Text(container, SWT.SINGLE | SWT.BORDER); - nameField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + nameField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); } private void createMainClassField(Composite container) { Label label = new Label(container, SWT.NONE); label.setText("&Main class:"); - Composite row = new Composite(container, SWT.NONE); - row.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - GridLayout rowLayout = new GridLayout(2, false); - rowLayout.marginWidth = 2; - row.setLayout(rowLayout); - - mainClassField = new Text(row, SWT.SINGLE | SWT.BORDER); + mainClassField = new Text(container, SWT.SINGLE | SWT.BORDER); mainClassField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - mainClassChooseButton = new Button(row, SWT.PUSH); + mainClassChooseButton = new Button(container, SWT.PUSH); mainClassChooseButton.setText("Choose..."); mainClassChooseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -110,28 +303,28 @@ public class TeaVMProfileDialog extends Dialog { 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(3, false); - rowLayout.marginWidth = 2; - row.setLayout(rowLayout); - - targetDirectoryField = new Text(row, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); + targetDirectoryField = new Text(container, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); targetDirectoryField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - targetDirectoryWorkspaceButton = new Button(row, SWT.PUSH); + targetDirectoryWorkspaceButton = new Button(container, SWT.PUSH); targetDirectoryWorkspaceButton.setText("Workspace..."); targetDirectoryWorkspaceButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - chooseWorkspaceTargetDirectory(); + String dir = chooseWorkspaceDirectory("Please, select a target directory"); + if (dir != null) { + targetDirectoryField.setText(dir); + } } }); - targetDirectoryFileSystemButton = new Button(row, SWT.PUSH); + targetDirectoryFileSystemButton = new Button(container, SWT.PUSH); targetDirectoryFileSystemButton.setText("External..."); targetDirectoryFileSystemButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - chooseFileSystemTargetDirectory(); + String dir = chooseFileSystemDirectory("Please, select a target directory"); + if (dir != null) { + targetDirectoryField.setText(dir); + } } }); } @@ -141,13 +334,77 @@ public class TeaVMProfileDialog extends Dialog { label.setText("&Target file:"); targetFileNameField = new Text(container, SWT.SINGLE | SWT.BORDER); - targetFileNameField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + targetFileNameField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); + } + + private void createRuntimeField(Composite container) { + Label label = new Label(container, SWT.NONE); + label.setText("Attach &runtime:"); + + runtimeField = new Combo(container, SWT.DROP_DOWN | SWT.READ_ONLY); + runtimeField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1)); + runtimeField.add("as a separate file (runtime.js)"); + runtimeField.add("merge into output file"); + runtimeField.add("don't attach"); } private void createMinifyField(Composite container) { minifyingButton = new Button(container, SWT.CHECK); - minifyingButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1)); - minifyingButton.setText("generate minified (obfuscated) code"); + minifyingButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1)); + minifyingButton.setText("generate minified (&obfuscated) code"); + } + + private void createIncrementalField(Composite container) { + incrementalButton = new Button(container, SWT.CHECK); + incrementalButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1)); + incrementalButton.setText("Build &incrementally"); + incrementalButton.addSelectionListener(new SelectionAdapter() { + @Override public void widgetSelected(SelectionEvent e) { + updateCacheFieldsEnabled(); + } + }); + } + + private void createCacheDirectoryField(Composite container) { + Label label = new Label(container, SWT.NONE); + label.setText("Cac&he directory:"); + + cacheDirectoryField = new Text(container, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); + cacheDirectoryField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + cacheDirectoryWorkspaceButton = new Button(container, SWT.PUSH); + cacheDirectoryWorkspaceButton.setText("Workspace..."); + cacheDirectoryWorkspaceButton.addSelectionListener(new SelectionAdapter() { + @Override public void widgetSelected(SelectionEvent e) { + String dir = chooseWorkspaceDirectory("Please, select a directory for the incremental cache"); + if (dir != null) { + cacheDirectoryField.setText(dir); + } + } + }); + + cacheDirectoryFileSystemButton = new Button(container, SWT.PUSH); + cacheDirectoryFileSystemButton.setText("External..."); + cacheDirectoryFileSystemButton.addSelectionListener(new SelectionAdapter() { + @Override public void widgetSelected(SelectionEvent e) { + String dir = chooseFileSystemDirectory("Please, select a directory for the incremental cache"); + if (dir != null) { + cacheDirectoryField.setText(dir); + } + } + }); + + updateCacheFieldsEnabled(); + } + + private void createDebugInformationField(Composite container) { + debugInformationButton = new Button(container, SWT.CHECK); + debugInformationButton.setText("Generate debug information for TeaVM native debugger"); + } + + private void createSourceMapsField(Composite container) { + sourceMapsButton = new Button(container, SWT.CHECK); + sourceMapsButton.setText("Generate source maps"); } public void setProject(IProject project) throws CoreException { @@ -169,11 +426,11 @@ public class TeaVMProfileDialog extends Dialog { } } - private void chooseWorkspaceTargetDirectory() { + private String chooseWorkspaceDirectory(String prompt) { 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.setTitle("Selecting directory"); + dialog.setMessage(prompt); dialog.setInput(ResourcesPlugin.getWorkspace().getRoot()); dialog.setComparator(new ResourceComparator(ResourceComparator.NAME)); if (dialog.open() == IDialogConstants.OK_ID) { @@ -182,18 +439,18 @@ public class TeaVMProfileDialog extends Dialog { String path = resource.getFullPath().toString(); String fileLoc = VariablesPlugin.getDefault().getStringVariableManager() .generateVariableExpression("workspace_loc", path); - targetDirectoryField.setText(fileLoc); + return fileLoc; } } + return null; } - private void chooseFileSystemTargetDirectory() { + private String chooseFileSystemDirectory(String prompt) { String filePath = targetDirectoryField.getText(); DirectoryDialog dialog = new DirectoryDialog(getShell()); + dialog.setMessage(prompt); filePath = dialog.open(); - if (filePath != null) { - targetDirectoryField.setText(filePath); - } + return filePath; } @Override @@ -208,12 +465,32 @@ public class TeaVMProfileDialog extends Dialog { } } + private void updateCacheFieldsEnabled() { + cacheDirectoryField.setEnabled(incrementalButton.getSelection()); + cacheDirectoryFileSystemButton.setEnabled(incrementalButton.getSelection()); + cacheDirectoryWorkspaceButton.setEnabled(incrementalButton.getSelection()); + } + private void load() { nameField.setText(profile.getName()); mainClassField.setText(profile.getMainClass() != null ? profile.getMainClass() : ""); targetDirectoryField.setText(profile.getTargetDirectory()); targetFileNameField.setText(profile.getTargetFileName()); minifyingButton.setSelection(profile.isMinifying()); + runtimeField.select(runtimeModes.indexOf(profile.getRuntimeMode())); + incrementalButton.setSelection(profile.isIncremental()); + cacheDirectoryField.setText(profile.getCacheDirectory()); + debugInformationButton.setSelection(profile.isDebugInformationGenerated()); + sourceMapsButton.setSelection(profile.isSourceMapsGenerated()); + propertyList.clear(); + Properties properties = profile.getProperties(); + for (Object key : properties.keySet()) { + KeyValue property = new KeyValue(); + property.key = (String)key; + property.value = properties.getProperty((String)key); + propertyList.add(property); + } + updateCacheFieldsEnabled(); } private boolean save() { @@ -228,6 +505,17 @@ public class TeaVMProfileDialog extends Dialog { profile.setTargetDirectory(targetDirectoryField.getText()); profile.setTargetFileName(targetFileNameField.getText().trim()); profile.setMinifying(minifyingButton.getSelection()); + profile.setRuntimeMode(runtimeModes.get(runtimeField.getSelectionIndex())); + profile.setIncremental(incrementalButton.getSelection()); + profile.setCacheDirectory(cacheDirectoryField.getText()); + profile.setDebugInformationGenerated(debugInformationButton.getSelection()); + profile.setSourceMapsGenerated(sourceMapsButton.getSelection()); + Properties properties = new Properties(); + for (Object item : propertyList) { + KeyValue property = (KeyValue)item; + properties.setProperty(property.key, property.value); + } + profile.setProperties(properties); return true; } } diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyPage.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyPage.java index 22ade39f0..12e0ababc 100644 --- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyPage.java +++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyPage.java @@ -4,6 +4,7 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -181,6 +182,11 @@ public class TeaVMProjectPropertyPage extends PropertyPage implements IWorkbench return; } TableItem item = profilesTable.getSelection()[0]; + boolean confirmed = MessageDialog.openConfirm(getShell(), "Deletion confirmation", + "Are you sure to delete profile " + item.getText(0) + "?"); + if (!confirmed) { + return; + } settings.deleteProfile((TeaVMProfile)item.getData()); item.dispose(); } @@ -189,6 +195,10 @@ public class TeaVMProjectPropertyPage extends PropertyPage implements IWorkbench public boolean performOk() { try { updateNature(); + for (int i = 0; i < profilesTable.getItemCount(); ++i) { + TableItem item = profilesTable.getItem(i); + storeItem(item); + } settings.save(); } catch (CoreException e) { reportStatus(e.getStatus());