Add support for multiple scripting languages
This commit is contained in:
parent
eb5321e82c
commit
a39a3fce15
core
resources/l10n
src/net/sf/openrocket
test/net/sf/openrocket/util
swing/src/net/sf/openrocket
simulation/extension
utils
@ -407,7 +407,7 @@ SimulationExtension.javacode.className = Fully-qualified Java class name:
|
|||||||
|
|
||||||
SimulationExtension.scripting.name = {language} script
|
SimulationExtension.scripting.name = {language} script
|
||||||
SimulationExtension.scripting.desc = Extend OpenRocket simulations by custom scripts.
|
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.plot = Plot
|
||||||
SimulationEditDialog.btn.export = Export
|
SimulationEditDialog.btn.export = Export
|
||||||
|
@ -13,10 +13,10 @@ import net.sf.openrocket.simulation.listeners.SimulationListener;
|
|||||||
|
|
||||||
public class ScriptingExtension extends AbstractSimulationExtension {
|
public class ScriptingExtension extends AbstractSimulationExtension {
|
||||||
|
|
||||||
private static final String JS = "JavaScript";
|
private static final String DEFAULT_LANGUAGE = "JavaScript";
|
||||||
|
|
||||||
public ScriptingExtension() {
|
public ScriptingExtension() {
|
||||||
setLanguage(JS);
|
setLanguage(DEFAULT_LANGUAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -46,8 +46,7 @@ public class ScriptingExtension extends AbstractSimulationExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getLanguage() {
|
public String getLanguage() {
|
||||||
// TODO: Support other languages
|
return config.getString("language", DEFAULT_LANGUAGE);
|
||||||
return JS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLanguage(String language) {
|
public void setLanguage(String language) {
|
||||||
@ -57,7 +56,10 @@ public class ScriptingExtension extends AbstractSimulationExtension {
|
|||||||
|
|
||||||
SimulationListener getListener() throws SimulationException {
|
SimulationListener getListener() throws SimulationException {
|
||||||
ScriptEngineManager manager = new ScriptEngineManager();
|
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 {
|
try {
|
||||||
engine.eval(getScript());
|
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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
swing/src/net/sf/openrocket/simulation/extension/AbstractSwingSimulationExtensionConfigurator.java
13
swing/src/net/sf/openrocket/simulation/extension/AbstractSwingSimulationExtensionConfigurator.java
@ -24,6 +24,8 @@ public abstract class AbstractSwingSimulationExtensionConfigurator<E extends Sim
|
|||||||
|
|
||||||
private final Class<E> extensionClass;
|
private final Class<E> extensionClass;
|
||||||
|
|
||||||
|
private JDialog dialog;
|
||||||
|
|
||||||
protected AbstractSwingSimulationExtensionConfigurator(Class<E> extensionClass) {
|
protected AbstractSwingSimulationExtensionConfigurator(Class<E> extensionClass) {
|
||||||
this.extensionClass = extensionClass;
|
this.extensionClass = extensionClass;
|
||||||
}
|
}
|
||||||
@ -37,7 +39,7 @@ public abstract class AbstractSwingSimulationExtensionConfigurator<E extends Sim
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void configure(SimulationExtension extension, Simulation simulation, Window parent) {
|
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 panel = new JPanel(new MigLayout("fill"));
|
||||||
JPanel sub = new JPanel(new MigLayout("fill, ins 0"));
|
JPanel sub = new JPanel(new MigLayout("fill, ins 0"));
|
||||||
|
|
||||||
@ -55,6 +57,8 @@ public abstract class AbstractSwingSimulationExtensionConfigurator<E extends Sim
|
|||||||
dialog.add(panel);
|
dialog.add(panel);
|
||||||
GUIUtil.setDisposableDialogOptions(dialog, close);
|
GUIUtil.setDisposableDialogOptions(dialog, close);
|
||||||
dialog.setVisible(true);
|
dialog.setVisible(true);
|
||||||
|
GUIUtil.setNullModels(dialog);
|
||||||
|
dialog = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,6 +68,13 @@ public abstract class AbstractSwingSimulationExtensionConfigurator<E extends Sim
|
|||||||
return extension.getName();
|
return extension.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the dialog currently open.
|
||||||
|
*/
|
||||||
|
protected JDialog getDialog() {
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract JComponent getConfigurationComponent(E extension, Simulation simulation, JPanel panel);
|
protected abstract JComponent getConfigurationComponent(E extension, Simulation simulation, JPanel panel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
package net.sf.openrocket.simulation.extension.impl;
|
package net.sf.openrocket.simulation.extension.impl;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.FocusListener;
|
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.JComponent;
|
||||||
import javax.swing.JPanel;
|
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.gui.components.StyledLabel.Style;
|
||||||
import net.sf.openrocket.plugin.Plugin;
|
import net.sf.openrocket.plugin.Plugin;
|
||||||
import net.sf.openrocket.simulation.extension.AbstractSwingSimulationExtensionConfigurator;
|
import net.sf.openrocket.simulation.extension.AbstractSwingSimulationExtensionConfigurator;
|
||||||
|
import net.sf.openrocket.util.ScriptingUtil;
|
||||||
|
|
||||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||||
|
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
|
||||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||||
|
|
||||||
@Plugin
|
@Plugin
|
||||||
public class ScriptingConfigurator extends AbstractSwingSimulationExtensionConfigurator<ScriptingExtension> {
|
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);
|
super(ScriptingExtension.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected JComponent getConfigurationComponent(final ScriptingExtension extension, Simulation simulation, JPanel panel) {
|
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.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
|
||||||
text.setCodeFoldingEnabled(true);
|
text.setCodeFoldingEnabled(true);
|
||||||
text.setLineWrap(true);
|
text.setLineWrap(true);
|
||||||
@ -51,9 +79,44 @@ public class ScriptingConfigurator extends AbstractSwingSimulationExtensionConfi
|
|||||||
});
|
});
|
||||||
|
|
||||||
RTextScrollPane scroll = new RTextScrollPane(text);
|
RTextScrollPane scroll = new RTextScrollPane(text);
|
||||||
panel.add(scroll, "grow");
|
panel.add(scroll, "spanx, grow");
|
||||||
|
|
||||||
|
setLanguage(ScriptingUtil.getLanguage(extension.getLanguage()));
|
||||||
|
|
||||||
return panel;
|
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