Add support for multiple scripting languages
This commit is contained in:
parent
eb5321e82c
commit
a39a3fce15
@ -407,7 +407,7 @@ SimulationExtension.javacode.className = Fully-qualified Java class name:
|
||||
|
||||
SimulationExtension.scripting.name = {language} script
|
||||
SimulationExtension.scripting.desc = Extend OpenRocket simulations by custom scripts.
|
||||
SimulationExtension.scripting.script.label = JavaScript code:
|
||||
SimulationExtension.scripting.language.label = Language:
|
||||
|
||||
SimulationEditDialog.btn.plot = Plot
|
||||
SimulationEditDialog.btn.export = Export
|
||||
|
@ -13,10 +13,10 @@ import net.sf.openrocket.simulation.listeners.SimulationListener;
|
||||
|
||||
public class ScriptingExtension extends AbstractSimulationExtension {
|
||||
|
||||
private static final String JS = "JavaScript";
|
||||
private static final String DEFAULT_LANGUAGE = "JavaScript";
|
||||
|
||||
public ScriptingExtension() {
|
||||
setLanguage(JS);
|
||||
setLanguage(DEFAULT_LANGUAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -46,8 +46,7 @@ public class ScriptingExtension extends AbstractSimulationExtension {
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
// TODO: Support other languages
|
||||
return JS;
|
||||
return config.getString("language", DEFAULT_LANGUAGE);
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
@ -57,7 +56,10 @@ public class ScriptingExtension extends AbstractSimulationExtension {
|
||||
|
||||
SimulationListener getListener() throws SimulationException {
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
ScriptEngine engine = manager.getEngineByName("JavaScript");
|
||||
ScriptEngine engine = manager.getEngineByName(getLanguage());
|
||||
if (engine == null) {
|
||||
throw new SimulationException("Your JRE does not support the scripting language '" + getLanguage() + "'");
|
||||
}
|
||||
|
||||
try {
|
||||
engine.eval(getScript());
|
||||
|
53
core/src/net/sf/openrocket/util/ScriptingUtil.java
Normal file
53
core/src/net/sf/openrocket/util/ScriptingUtil.java
Normal file
@ -0,0 +1,53 @@
|
||||
package net.sf.openrocket.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import javax.script.ScriptEngineManager;
|
||||
|
||||
public class ScriptingUtil {
|
||||
|
||||
/** The name to be chosen from a list of alternatives. If not found, will use the default name. */
|
||||
private static final List<String> PREFERRED_LANGUAGE_NAMES = Arrays.asList("JavaScript");
|
||||
|
||||
/**
|
||||
* Return the preferred internal language name based on a script language name.
|
||||
*
|
||||
* @return the preferred language name, or null if the language is not supported.
|
||||
*/
|
||||
public static String getLanguage(String language) {
|
||||
if (language == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
ScriptEngine engine = manager.getEngineByName(language);
|
||||
if (engine == null) {
|
||||
return null;
|
||||
}
|
||||
return getLanguage(engine.getFactory());
|
||||
}
|
||||
|
||||
|
||||
public static List<String> getLanguages() {
|
||||
List<String> langs = new ArrayList<String>();
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
for (ScriptEngineFactory factory : manager.getEngineFactories()) {
|
||||
langs.add(getLanguage(factory));
|
||||
}
|
||||
return langs;
|
||||
}
|
||||
|
||||
|
||||
private static String getLanguage(ScriptEngineFactory factory) {
|
||||
for (String name : factory.getNames()) {
|
||||
if (PREFERRED_LANGUAGE_NAMES.contains(name)) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
return factory.getLanguageName();
|
||||
}
|
||||
}
|
32
core/test/net/sf/openrocket/util/TestScriptingUtil.java
Normal file
32
core/test/net/sf/openrocket/util/TestScriptingUtil.java
Normal file
@ -0,0 +1,32 @@
|
||||
package net.sf.openrocket.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestScriptingUtil {
|
||||
|
||||
/*
|
||||
* Note: This class assumes that the JRE supports JavaScript scripting.
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testGetLanguage() {
|
||||
assertEquals(null, ScriptingUtil.getLanguage(null));
|
||||
assertEquals(null, ScriptingUtil.getLanguage(""));
|
||||
assertEquals(null, ScriptingUtil.getLanguage("foobar"));
|
||||
assertEquals("JavaScript", ScriptingUtil.getLanguage("JavaScript"));
|
||||
assertEquals("JavaScript", ScriptingUtil.getLanguage("javascript"));
|
||||
assertEquals("JavaScript", ScriptingUtil.getLanguage("ECMAScript"));
|
||||
assertEquals("JavaScript", ScriptingUtil.getLanguage("js"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetLanguages() {
|
||||
assertTrue(ScriptingUtil.getLanguages().size() >= 1);
|
||||
assertTrue(ScriptingUtil.getLanguages().contains("JavaScript"));
|
||||
}
|
||||
|
||||
}
|
@ -24,6 +24,8 @@ public abstract class AbstractSwingSimulationExtensionConfigurator<E extends Sim
|
||||
|
||||
private final Class<E> extensionClass;
|
||||
|
||||
private JDialog dialog;
|
||||
|
||||
protected AbstractSwingSimulationExtensionConfigurator(Class<E> extensionClass) {
|
||||
this.extensionClass = extensionClass;
|
||||
}
|
||||
@ -37,7 +39,7 @@ public abstract class AbstractSwingSimulationExtensionConfigurator<E extends Sim
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void configure(SimulationExtension extension, Simulation simulation, Window parent) {
|
||||
final JDialog dialog = new JDialog(parent, getTitle(extension, simulation), ModalityType.APPLICATION_MODAL);
|
||||
dialog = new JDialog(parent, getTitle(extension, simulation), ModalityType.APPLICATION_MODAL);
|
||||
JPanel panel = new JPanel(new MigLayout("fill"));
|
||||
JPanel sub = new JPanel(new MigLayout("fill, ins 0"));
|
||||
|
||||
@ -55,6 +57,8 @@ public abstract class AbstractSwingSimulationExtensionConfigurator<E extends Sim
|
||||
dialog.add(panel);
|
||||
GUIUtil.setDisposableDialogOptions(dialog, close);
|
||||
dialog.setVisible(true);
|
||||
GUIUtil.setNullModels(dialog);
|
||||
dialog = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,6 +68,13 @@ public abstract class AbstractSwingSimulationExtensionConfigurator<E extends Sim
|
||||
return extension.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the dialog currently open.
|
||||
*/
|
||||
protected JDialog getDialog() {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
protected abstract JComponent getConfigurationComponent(E extension, Simulation simulation, JPanel panel);
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,15 @@
|
||||
package net.sf.openrocket.simulation.extension.impl;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
@ -12,24 +18,46 @@ import net.sf.openrocket.gui.components.StyledLabel;
|
||||
import net.sf.openrocket.gui.components.StyledLabel.Style;
|
||||
import net.sf.openrocket.plugin.Plugin;
|
||||
import net.sf.openrocket.simulation.extension.AbstractSwingSimulationExtensionConfigurator;
|
||||
import net.sf.openrocket.util.ScriptingUtil;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
|
||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||
|
||||
@Plugin
|
||||
public class ScriptingConfigurator extends AbstractSwingSimulationExtensionConfigurator<ScriptingExtension> {
|
||||
|
||||
protected ScriptingConfigurator() {
|
||||
private JComboBox languageSelector;
|
||||
private RSyntaxTextArea text;
|
||||
|
||||
private ScriptingExtension extension;
|
||||
private Simulation simulation;
|
||||
|
||||
public ScriptingConfigurator() {
|
||||
super(ScriptingExtension.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent getConfigurationComponent(final ScriptingExtension extension, Simulation simulation, JPanel panel) {
|
||||
this.extension = extension;
|
||||
this.simulation = simulation;
|
||||
|
||||
panel.add(new StyledLabel(trans.get("SimulationExtension.scripting.script.label"), Style.BOLD), "wrap");
|
||||
panel.add(new StyledLabel(trans.get("SimulationExtension.scripting.language.label"), Style.BOLD), "");
|
||||
|
||||
final RSyntaxTextArea text = new RSyntaxTextArea(extension.getScript(), 15, 60);
|
||||
String[] languages = ScriptingUtil.getLanguages().toArray(new String[0]);
|
||||
languageSelector = new JComboBox(languages);
|
||||
languageSelector.setEditable(false);
|
||||
languageSelector.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
setLanguage((String) languageSelector.getSelectedItem());
|
||||
}
|
||||
});
|
||||
panel.add(languageSelector, "wrap para");
|
||||
|
||||
|
||||
text = new RSyntaxTextArea(extension.getScript(), 15, 60);
|
||||
text.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
|
||||
text.setCodeFoldingEnabled(true);
|
||||
text.setLineWrap(true);
|
||||
@ -51,9 +79,44 @@ public class ScriptingConfigurator extends AbstractSwingSimulationExtensionConfi
|
||||
});
|
||||
|
||||
RTextScrollPane scroll = new RTextScrollPane(text);
|
||||
panel.add(scroll, "grow");
|
||||
panel.add(scroll, "spanx, grow");
|
||||
|
||||
setLanguage(ScriptingUtil.getLanguage(extension.getLanguage()));
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void setLanguage(String language) {
|
||||
if (language == null) {
|
||||
language = "";
|
||||
}
|
||||
if (!language.equals(languageSelector.getSelectedItem())) {
|
||||
languageSelector.setSelectedItem(language);
|
||||
}
|
||||
extension.setLanguage(language);
|
||||
text.setSyntaxEditingStyle(findSyntaxLanguage(language));
|
||||
getDialog().setTitle(getTitle(extension, simulation));
|
||||
}
|
||||
|
||||
private String findSyntaxLanguage(String language) {
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
ScriptEngine engine = manager.getEngineByName(language);
|
||||
|
||||
if (engine != null) {
|
||||
Set<String> supported = TokenMakerFactory.getDefaultInstance().keySet();
|
||||
for (String type : engine.getFactory().getMimeTypes()) {
|
||||
if (supported.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
for (String match : supported) {
|
||||
if (match.contains("/" + language.toLowerCase())) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SyntaxConstants.SYNTAX_STYLE_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
|
38
swing/src/net/sf/openrocket/utils/Scripting.java
Normal file
38
swing/src/net/sf/openrocket/utils/Scripting.java
Normal file
@ -0,0 +1,38 @@
|
||||
package net.sf.openrocket.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import javax.script.ScriptEngineManager;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
|
||||
|
||||
public class Scripting {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Scripting APIs:");
|
||||
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
for (ScriptEngineFactory factory : manager.getEngineFactories()) {
|
||||
System.out.println(" engineName=" + factory.getEngineName() +
|
||||
" engineVersion=" + factory.getEngineVersion() +
|
||||
" languageName=" + factory.getLanguageName() +
|
||||
" languageVersion=" + factory.getLanguageVersion() +
|
||||
" names=" + factory.getNames() +
|
||||
" mimeTypes=" + factory.getMimeTypes() +
|
||||
" extensions=" + factory.getExtensions());
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
System.out.println("RSyntaxTextArea supported syntax languages:");
|
||||
TokenMakerFactory f = TokenMakerFactory.getDefaultInstance();
|
||||
List<String> list = new ArrayList<String>(f.keySet());
|
||||
Collections.sort(list);
|
||||
for (String type : list) {
|
||||
System.out.println(" " + type);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user