Skip to content

Commit 1954dc2

Browse files
committed
Make the interpreter use the new SJC REPL
This gives it access to the REPL's meta-commands (:langs, :vars, etc.). It also eliminates the ugly tabs in favor of one simpler unified pane.
1 parent 4e06079 commit 1954dc2

File tree

4 files changed

+126
-218
lines changed

4 files changed

+126
-218
lines changed

src/main/java/org/scijava/ui/swing/script/InterpreterPane.java

Lines changed: 48 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -40,70 +40,62 @@
4040
import javax.script.ScriptContext;
4141
import javax.script.ScriptException;
4242
import javax.swing.JButton;
43+
import javax.swing.JComponent;
4344
import javax.swing.JPanel;
4445
import javax.swing.JScrollPane;
4546
import javax.swing.JSplitPane;
4647

4748
import net.miginfocom.swing.MigLayout;
4849

50+
import org.scijava.Context;
4951
import org.scijava.log.LogService;
50-
import org.scijava.prefs.PrefService;
51-
import org.scijava.script.DefaultScriptInterpreter;
52-
import org.scijava.script.ScriptInterpreter;
53-
import org.scijava.script.ScriptLanguage;
54-
import org.scijava.script.ScriptService;
52+
import org.scijava.plugin.Parameter;
53+
import org.scijava.script.ScriptREPL;
54+
import org.scijava.widget.UIComponent;
5555

5656
/**
57-
* A Swing UI pane for a language-specific script interpreter.
57+
* A Swing UI pane for the SciJava scripting REPL.
5858
*
5959
* @author Curtis Rueden
6060
* @author Johannes Schindelin
6161
*/
62-
public class InterpreterPane {
62+
public class InterpreterPane implements UIComponent<JComponent> {
6363

64-
private final ScriptInterpreter interpreter;
64+
private final ScriptREPL repl;
6565

6666
private final JSplitPane splitPane;
6767
private final OutputPane output;
6868
private final PromptPane prompt;
6969

70-
/**
71-
* Constructs an interpreter UI pane for a specific scripting language.
72-
*
73-
* @param prefs service to use for persisting the history
74-
* @param scriptService service to use for scripting
75-
* @param language scripting language for which to construct a UI pane
76-
* @param log service to use for logging
77-
*/
78-
public InterpreterPane(final PrefService prefs,
79-
final ScriptService scriptService, final ScriptLanguage language,
80-
final LogService log)
81-
{
82-
this(createInterpreter(prefs, scriptService, language), log);
83-
}
70+
@Parameter(required = false)
71+
private LogService log;
8472

8573
/**
86-
* Constructs an interpreter UI pane for a specific script interpreter.
74+
* Constructs an interpreter UI pane for a SciJava scripting REPL.
8775
*
88-
* @param interpreter script interpreter to use for script execution
89-
* @param log service to use for logging
76+
* @param context The SciJava application context to use
9077
*/
91-
public InterpreterPane(final ScriptInterpreter interpreter,
92-
final LogService log)
93-
{
94-
this.interpreter = interpreter;
95-
78+
public InterpreterPane(final Context context) {
79+
context.inject(this);
9680
output = new OutputPane(log);
9781
final JScrollPane outputScroll = new JScrollPane(output);
9882
outputScroll.setPreferredSize(new Dimension(440, 400));
9983

84+
repl = new ScriptREPL(context, output.getOutputStream());
85+
repl.initialize();
86+
10087
final Writer writer = output.getOutputWriter();
101-
final ScriptContext context = interpreter.getEngine().getContext();
102-
context.setErrorWriter(writer);
103-
context.setWriter(writer);
88+
final ScriptContext ctx = repl.getInterpreter().getEngine().getContext();
89+
ctx.setErrorWriter(writer);
90+
ctx.setWriter(writer);
10491

105-
prompt = new PromptPane(interpreter, output);
106-
final JScrollPane promptScroll = new JScrollPane(prompt);
92+
prompt = new PromptPane(repl, output) {
93+
@Override
94+
public void quit() {
95+
dispose();
96+
}
97+
};
98+
final JScrollPane promptScroll = new JScrollPane(prompt.getComponent());
10799

108100
final JButton clearButton = new JButton("Clear");
109101
clearButton.setToolTipText("Clears the text in the output pane.");
@@ -121,9 +113,8 @@ public void actionPerformed(final ActionEvent e) {
121113
bottomPane.add(promptScroll, "spany 2");
122114
bottomPane.add(clearButton, "w pref!, h pref!, wrap");
123115

124-
final Object importGenerator =
125-
DefaultAutoImporters.getImportGenerator(log.getContext(), interpreter
126-
.getLanguage());
116+
final Object importGenerator = DefaultAutoImporters.getImportGenerator(
117+
log.getContext(), repl.getInterpreter().getLanguage());
127118
if (importGenerator != null) {
128119
final JButton autoImportButton = new JButton("Auto-Import");
129120
autoImportButton.setToolTipText("Auto-imports common classes.");
@@ -132,13 +123,13 @@ public void actionPerformed(final ActionEvent e) {
132123
@Override
133124
public void actionPerformed(final ActionEvent e) {
134125
try {
135-
interpreter.getEngine().eval(importGenerator.toString());
126+
repl.getInterpreter().getEngine().eval(importGenerator.toString());
136127
}
137128
catch (final ScriptException e1) {
138129
e1.printStackTrace(new PrintWriter(output.getOutputWriter()));
139130
}
140131
autoImportButton.setEnabled(false);
141-
prompt.requestFocus();
132+
prompt.getComponent().requestFocus();
142133
}
143134
});
144135
bottomPane.add(autoImportButton, "w pref!, h pref!, wrap");
@@ -149,23 +140,14 @@ public void actionPerformed(final ActionEvent e) {
149140
splitPane.setResizeWeight(1);
150141
}
151142

152-
public void dispose() throws IOException {
153-
output.close();
154-
}
155-
156143
// -- InterpreterPane methods --
157144

158-
/** Gets the associated script interpreter. */
159-
public ScriptInterpreter getInterpreter() {
160-
return interpreter;
145+
/** Gets the associated script REPL. */
146+
public ScriptREPL getREPL() {
147+
return repl;
161148
}
162149

163-
/** Gets the pane's Swing UI component. */
164-
public JSplitPane getComponent() {
165-
return splitPane;
166-
}
167-
168-
/** Print a message to the output panel */
150+
/** Prints a message to the output panel. */
169151
public void print(final String string) {
170152
final Writer writer = output.getOutputWriter();
171153
try {
@@ -176,12 +158,20 @@ public void print(final String string) {
176158
}
177159
}
178160

179-
// -- Utility methods --
161+
public void dispose() {
162+
output.close();
163+
}
164+
165+
// -- UIComponent methods --
166+
167+
@Override
168+
public JComponent getComponent() {
169+
return splitPane;
170+
}
180171

181-
public static ScriptInterpreter createInterpreter(final PrefService prefs,
182-
final ScriptService scriptService, final ScriptLanguage language)
183-
{
184-
return new DefaultScriptInterpreter(prefs, scriptService, language);
172+
@Override
173+
public Class<JComponent> getComponentType() {
174+
return JComponent.class;
185175
}
186176

187177
}

src/main/java/org/scijava/ui/swing/script/InterpreterWindow.java

Lines changed: 12 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,13 @@
3030

3131
package org.scijava.ui.swing.script;
3232

33-
import java.beans.PropertyChangeEvent;
34-
import java.beans.PropertyChangeListener;
35-
import java.util.ArrayList;
36-
import java.util.Collections;
37-
import java.util.Comparator;
38-
import java.util.Iterator;
39-
import java.util.List;
40-
4133
import javax.swing.JFrame;
42-
import javax.swing.JSplitPane;
43-
import javax.swing.JTabbedPane;
4434
import javax.swing.WindowConstants;
4535

4636
import org.scijava.Context;
4737
import org.scijava.log.LogService;
4838
import org.scijava.plugin.Parameter;
4939
import org.scijava.prefs.PrefService;
50-
import org.scijava.script.ScriptLanguage;
5140
import org.scijava.script.ScriptService;
5241

5342
/**
@@ -58,6 +47,8 @@
5847
*/
5948
public class InterpreterWindow extends JFrame {
6049

50+
private final InterpreterPane pane;
51+
6152
@Parameter
6253
private PrefService prefs;
6354

@@ -67,29 +58,19 @@ public class InterpreterWindow extends JFrame {
6758
@Parameter
6859
private LogService log;
6960

70-
private final List<InterpreterPane> tabs = new ArrayList<InterpreterPane>();
71-
private final JTabbedPane tabbedPane;
72-
7361
/** Constructs the scripting interpreter window. */
7462
public InterpreterWindow(final Context context) {
7563
super("Script Interpreter");
7664
context.inject(this);
7765

78-
tabbedPane = new JTabbedPane();
79-
setContentPane(tabbedPane);
80-
81-
for (final ScriptLanguage language : languages()) {
82-
final String name = language.getLanguageName();
83-
final InterpreterPane tab =
84-
new InterpreterPane(prefs, scriptService, language, log);
85-
tabs.add(tab);
86-
tabbedPane.add(name, tab.getComponent());
87-
}
88-
89-
syncTabs();
90-
91-
// read in interpreter histories, etc.
92-
readState();
66+
pane = new InterpreterPane(context) {
67+
@Override
68+
public void dispose() {
69+
super.dispose();
70+
InterpreterWindow.super.dispose();
71+
}
72+
};
73+
setContentPane(pane.getComponent());
9374

9475
pack();
9576

@@ -99,115 +80,14 @@ public InterpreterWindow(final Context context) {
9980
@Override
10081
public void dispose() {
10182
// write out interpreter histories, etc., when frame goes away
102-
writeState();
103-
for (final InterpreterPane tab : tabs)
104-
try {
105-
tab.dispose();
106-
}
107-
catch (final Exception e) {
108-
e.printStackTrace();
109-
}
83+
pane.dispose();
11084
super.dispose();
11185
}
11286

11387
// -- Helper methods --
11488

115-
/** Gets the list of available scripting languages, sorted by name. */
116-
private List<ScriptLanguage> languages() {
117-
final List<ScriptLanguage> languages =
118-
new ArrayList<ScriptLanguage>(scriptService.getLanguages());
119-
120-
// skip compiled languages (makes no sense to interpret them)
121-
for (final Iterator<ScriptLanguage> iter = languages.iterator(); iter
122-
.hasNext();)
123-
{
124-
if (iter.next().isCompiledLanguage()) iter.remove();
125-
}
126-
127-
Collections.sort(languages, new Comparator<ScriptLanguage>() {
128-
129-
@Override
130-
public int compare(final ScriptLanguage l1, final ScriptLanguage l2) {
131-
return l1.getLanguageName().compareTo(l2.getLanguageName());
132-
}
133-
134-
});
135-
return languages;
136-
}
137-
138-
/** Ensures that each tab's split pane stays sized the same. */
139-
private void syncTabs() {
140-
final PropertyChangeListener l = new PropertyChangeListener() {
141-
142-
@Override
143-
public void propertyChange(final PropertyChangeEvent evt) {
144-
final String prop = evt.getPropertyName();
145-
if (!prop.equals(JSplitPane.DIVIDER_LOCATION_PROPERTY)) return;
146-
final JSplitPane splitPane = (JSplitPane) evt.getSource();
147-
final int dividerLocation = splitPane.getDividerLocation();
148-
for (final InterpreterPane tab : tabs) {
149-
final JSplitPane c = tab.getComponent();
150-
if (c == splitPane) continue;
151-
c.setDividerLocation(dividerLocation);
152-
}
153-
}
154-
};
155-
for (final InterpreterPane tab : tabs) {
156-
tab.getComponent().addPropertyChangeListener(l);
157-
}
158-
}
159-
160-
/**
161-
* Reads in persisted state, including the last active tab, as well as the
162-
* history of each interpreter.
163-
*/
164-
private void readState() {
165-
setActiveLanguage(prefs.get(InterpreterWindow.class, "language"));
166-
for (final InterpreterPane tab : tabs) {
167-
tab.getInterpreter().readHistory();
168-
}
169-
}
170-
171-
/**
172-
* Writes out persisted state, including the currently active tab, as well as
173-
* the history of each interpreter.
174-
*/
175-
private void writeState() {
176-
final String active = getActiveLanguage();
177-
if (active != null) prefs.put(InterpreterWindow.class, "language", active);
178-
for (final InterpreterPane tab : tabs) {
179-
tab.getInterpreter().writeHistory();
180-
}
181-
}
182-
183-
/** Gets the name of the active language tab. */
184-
private String getActiveLanguage() {
185-
final int selected = tabbedPane.getSelectedIndex();
186-
if (selected < 0) return null;
187-
final InterpreterPane tab = tabs.get(selected);
188-
return tab.getInterpreter().getLanguage().getLanguageName();
189-
}
190-
191-
/** Sets the active language tab by name. */
192-
private void setActiveLanguage(final String languageName) {
193-
for (int i = 0; i < tabs.size(); i++) {
194-
final InterpreterPane tab = tabs.get(i);
195-
final String name = tab.getInterpreter().getLanguage().getLanguageName();
196-
if (name.equals(languageName)) {
197-
tabbedPane.setSelectedIndex(i);
198-
break;
199-
}
200-
}
201-
}
202-
20389
/** Print a message to the current language's output panel */
20490
public void print(final String string) {
205-
final int selected = tabbedPane.getSelectedIndex();
206-
if (selected < 0) {
207-
System.out.println(string);
208-
return;
209-
}
210-
final InterpreterPane tab = tabs.get(selected);
211-
tab.print(string);
91+
pane.print(string);
21292
}
21393
}

0 commit comments

Comments
 (0)