package bluej.debugmgr.codepad;
import bluej.BlueJEvent;
import bluej.Config;
import bluej.collect.DataCollector;
import bluej.debugger.DebuggerField;
import bluej.debugger.DebuggerObject;
import bluej.debugger.ExceptionDescription;
import bluej.debugger.gentype.JavaType;
import bluej.debugmgr.ExecutionEvent;
import bluej.debugmgr.IndexHistory;
import bluej.debugmgr.Invoker;
import bluej.debugmgr.NamedValue;
import bluej.debugmgr.ResultWatcher;
import bluej.debugmgr.ValueCollection;
import bluej.parser.TextAnalyzer;
import bluej.pkgmgr.PkgMgrFrame;
import bluej.pkgmgr.Project;
import bluej.prefmgr.PrefMgr;
import bluej.testmgr.record.InvokerRecord;
import bluej.utility.Utility;
import bluej.utility.javafx.FXPlatformRunnable;
import bluej.utility.javafx.JavaFXUtil;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.collections.ListChangeListener;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TextField;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Effect;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.DataFormat;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.QuadCurveTo;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.fxmisc.wellbehaved.event.EventPattern;
import org.fxmisc.wellbehaved.event.InputMap;
import org.fxmisc.wellbehaved.event.Nodes;
import threadchecker.OnThread;
import threadchecker.Tag;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
| A code pad which can evaluate fragments of Java code.
|
| In JavaFX this is built using a ListView. ListViews have virtualised
| cells, which means that only enough rows are created to display
| the currently visible portion of the scroll pane, not every row in the list.
| So if the user has a history 200 lines long, but only 8 lines are visible
| in the codepad, then no matter where they scroll to, only 8 display lines will be
| created, not 200.
|
| ListViews allow editing of any individual cell, but we hack it here so that
| (a) only the last row can be edited, and (b) the last row is *always* in an editing state.
| This means the users see one text field at the bottom of the list, and rows
| above that with the history (styled as we like).
|
@OnThread(Tag.FXPlatform)
public class CodePad
extends VBox
implements ValueCollection, PkgMgrFrame.PkgMgrPane{
| The list view containing all the history items:
|
private final ListView<HistoryRow> historyView;
| The edit field for input
|
private final TextField inputField;
| The pane on which to draw the arrows indicating what happens
| to clicked objects.
|
private final Pane arrowOverlay;
private BooleanBinding shadowShowing;
| A data item which backs a single row in the code pad.
| This might be the currently edited row (the last row), or
| a read-only item detailing a past command or command outcome;
|
private abstract static @OnThread(Tag.FX) class HistoryRow
{
private final String text;
@OnThread(Tag.Any)
public static enum RowStyle
{
COMMAND_PARTIAL("bj-codepad-cmd-partial"),
COMMAND_END("bj-codepad-cmd-end"),
ERROR("bj-codepad-error"),
OUTPUT("bj-codepad-output");
private final String pseudo;
public String getPseudoClass()
{
return pseudo;
}
private RowStyle(String pseudo)
{
this.pseudo = pseudo;
}
}
public HistoryRow(String text)
{
this.text = text;
}
public final String getText()
{
return text;
}
@Override
public String toString()
{
return getText();
}
public abstract Node getGraphic();
| Gets the graphical style that should be used for displaying this row.
|
public abstract RowStyle getStyle();
}
@OnThread(Tag.FX)
public static abstract class IndentedRow
extends HistoryRow
{
protected Rectangle r;
public IndentedRow(String text)
{
super(text);
r = new Rectangle(objectImage.getWidth(), objectImage.getHeight());
r.setVisible(false);
}
| Gets the graphic to display alongside the row
|
@Override
public Node getGraphic()
{
return r;
}
}
private static final String[] allRowStyles;
static {
allRowStyles = new String[HistoryRow.RowStyle.values().length];
for (int i = 0; i < HistoryRow.RowStyle.values().length; i++)
{
allRowStyles[i] = HistoryRow.RowStyle.values()[i].getPseudoClass();
}
}
| A row with a previously entered command. This may be a single
| complete row (e.g. 1+2) or it may be part of a multi-row
| command. We have a different pseudo-class for the last row
| of commands, but currently don't use it differently in the CSS file.
|
@OnThread(Tag.FX)
private static class CommandRow
extends HistoryRow
{
private final boolean isFinalLine;
public CommandRow(String text, boolean isFinalLine)
{
super(text);
this.isFinalLine = isFinalLine;
}
@Override
public Node getGraphic()
{
return null;
}
@Override
public RowStyle getStyle()
{
return isFinalLine ? RowStyle.COMMAND_END : RowStyle.COMMAND_PARTIAL;
}
}
| The successful output of a previous command. It may or may not
| have an object as an output.
|
@OnThread(Tag.FX)
private class OutputSuccessRow
extends IndentedRow
{
private final ImageView graphic;
private Path arrow;
private FXPlatformRunnable cancelAddToBench;
public OutputSuccessRow(String text, ObjectInfo objInfo)
{
super(text);
if (objInfo != null)
{
graphic = new ImageView(objectImage);
graphic.setMouseTransparent(false);
JavaFXUtil.addChangeListener(graphic.mouseTransparentProperty(), b -> {
if (b.booleanValue())
graphic.setMouseTransparent(false);
});
graphic.setCursor(Cursor.HAND);
graphic.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
if (e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 1)
{
cancelAddToBench = JavaFXUtil.runAfter(Duration.millis(500), () -> JavaFXUtil.runAfterCurrent(() -> {
Stage fxWindow = frame.getFXWindow();
Point2D from = graphic.localToScene(new Point2D(0.0, 0.0));
frame.getPackage().getEditor().raisePutOnBenchEvent(fxWindow, objInfo.obj, objInfo.obj.getGenType(), objInfo.ir, true, Optional.of(from));
cancelAddToBench = null;
}));
e.consume();
}
else if (e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 2)
{
if (cancelAddToBench != null)
{
cancelAddToBench.run();
cancelAddToBench = null;
}
Project project = frame.getProject();
if (project != null)
{
project.getInspectorInstance(objInfo.obj, "", frame.getPackage(), objInfo.ir, frame.getFXWindow(), graphic).bringToFront();
}
e.consume();
}
});
graphic.setOnMouseEntered(e -> {
graphic.setImage(objectImageHighlight);
graphic.setEffect(new ColorAdjust(0.0, -0.2, 0.45, 0.0));
if (arrow == null)
{
arrow = new Path();
JavaFXUtil.addStyleClass(arrow, "codepad-add-object-arrow");
double centreAngle = 35.0;
arrow.getElements().addAll(
new MoveTo(40.0, 10.0),
new QuadCurveTo(25.0, -10.0, 0.0, 10.0),
new LineTo(0 + Math.cos(Math.toRadians(centreAngle + 45.0))*10.0, 10.0 - Math.sin(Math.toRadians(centreAngle + 45.0))*10.0),
new MoveTo(0.0, 10.0),
new LineTo(0 + Math.cos(Math.toRadians(centreAngle - 45.0))*10.0, 10.0 - Math.sin(Math.toRadians(centreAngle - 45.0))*10.0)
);
}
Bounds b = arrowOverlay.sceneToLocal(graphic.localToScene(graphic.getBoundsInLocal()));
arrow.setLayoutX(b.getMinX() - 40.0);
arrow.setLayoutY(b.getMinY() - 10.0 + b.getHeight()*0.5);
arrowOverlay.getChildren().add(arrow);
});
graphic.setOnMouseExited(e -> {
graphic.setImage(objectImage);
graphic.setEffect(null);
arrowOverlay.getChildren().remove(arrow);
});
}
else{ graphic = null;
}
}
@Override
public Node getGraphic()
{
return graphic != null ? graphic : super.getGraphic();
}
@Override
public RowStyle getStyle()
{
return RowStyle.OUTPUT;
}
}
| A row with an error output of a previous command.
|
@OnThread(Tag.FX)
private static class ErrorRow
extends IndentedRow
{
public ErrorRow(String text)
{
super(text);
}
@Override
public RowStyle getStyle()
{
return RowStyle.ERROR;
}
}
private static final String nullLabel = "null";
private static final String uninitializedWarning = Config.getString("pkgmgr.codepad.uninitialized");
private static final Image objectImage =
Config.getImageAsFXImage("image.eval.object");
private static final Image objectImageHighlight =
Config.getImageAsFXImage("image.eval.object");
private final PkgMgrFrame frame;
@OnThread(Tag.FX)
private String currentCommand = "";
@OnThread(Tag.FX)
private IndexHistory history;
private Invoker invoker = null;
private TextAnalyzer textParser = null;
private boolean firstTry;
private boolean wrappedResult;
private String errorMessage;
private boolean busy = false;
private List<CodepadVar> localVars = new ArrayList<CodepadVar>();
private List<CodepadVar> newlyDeclareds;
private List<String> autoInitializedVars;
private Runnable removeHover;
public CodePad(PkgMgrFrame frame, Pane arrowOverlay)
{
this.frame = frame;
this.arrowOverlay = arrowOverlay;
JavaFXUtil.addStyleClass(this, "codepad");
setMinWidth(100.0);
inputField = new TextField();
JavaFXUtil.addStyleClass(inputField, "codepad-input");
inputField.setFocusTraversable(true);
inputField.setEditable(true);
historyView = new ListView<>();
historyView.setFocusTraversable(false);
historyView.setEditable(false);
inputField.styleProperty().bind(PrefMgr.getEditorFontCSS(false));
historyView.styleProperty().bind(PrefMgr.getEditorFontCSS(false));
Nodes.addInputMap(inputField, InputMap.sequence(
InputMap.consume(EventPattern.keyPressed(KeyCode.EQUALS, KeyCombination.SHORTCUT_DOWN), e -> Utility.increaseFontSize(PrefMgr.getEditorFontSize())),
InputMap.consume(EventPattern.keyPressed(KeyCode.MINUS, KeyCombination.SHORTCUT_DOWN), e -> Utility.decreaseFontSize(PrefMgr.getEditorFontSize()))
));
historyView.getItems().addListener(new ListChangeListener<HistoryRow>()
{
@Override
@OnThread(Tag.FX)
public void onChanged(Change<? extends HistoryRow> c)
{
ScrollBar scrollBar = (ScrollBar)historyView.lookup(".scroll-bar");
shadowShowing = scrollBar.visibleProperty().and(scrollBar.valueProperty().isNotEqualTo(1.0, 0.01));
inputField.effectProperty().bind(Bindings.when(shadowShowing).<Effect>then(new DropShadow(6.0, 0.0, -3.0, Color.GRAY)).otherwise((Effect)null));
historyView.getItems().removeListener(this);
}
});
JavaFXUtil.addStyleClass(historyView, "codepad-history");
getChildren().setAll(historyView, inputField);
VBox.setVgrow(historyView, Priority.ALWAYS);
history = new IndexHistory(20);
historyView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
historyView.setContextMenu(new ContextMenu(
JavaFXUtil.makeMenuItem(Config.getString("editor.copyLabel"), () -> copySelectedRows(), null),
JavaFXUtil.makeMenuItem(Config.getString("codepad.copyAll"), () -> {
historyView.getSelectionModel().selectAll();
copySelectedRows();
}, null),
JavaFXUtil.makeMenuItem(Config.getString("codepad.clear"), () -> {
historyView.getSelectionModel().clearSelection();
historyView.getItems().clear();
}, null)
));
historyView.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
if (e.getCode() == KeyCode.C && e.isShortcutDown())
{
copySelectedRows();
e.consume();
}
});
inputField.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
if (e.getCode() == KeyCode.UP)
{
historyBack();
e.consume();
}
else if (e.getCode() == KeyCode.DOWN)
{
historyForward();
e.consume();
}
else if (e.getCode() == KeyCode.ENTER && e.isShiftDown())
{
softReturn();
e.consume();
}
});
inputField.setOnAction(e -> {
String line = inputField.getText();
if (line.trim().isEmpty())
return;
command(line, true);
inputField.setEditable(false);
inputField.setText("");
currentCommand = (currentCommand + line).trim();
if (currentCommand.length() != 0)
{
history.add(line);
String cmd = currentCommand;
currentCommand = "";
executeCommand(cmd);
}
});
historyView.setCellFactory(lv -> new ListCell<HistoryRow>() { {
JavaFXUtil.addStyleClass(this, "codepad-row");
}
@Override
@OnThread(Tag.FX)
public void updateItem(HistoryRow item, boolean empty)
{
super.updateItem(item, empty);
if (!empty && item != null)
{
setGraphic(item.getGraphic());
setText(item.getText());
JavaFXUtil.selectPseudoClass(this, Arrays.asList(allRowStyles).indexOf(item.getStyle().getPseudoClass()), allRowStyles);
}
else
{
setGraphic(null);
setText("");
JavaFXUtil.selectPseudoClass(this, -1, allRowStyles);
}
}
});
}
private void copySelectedRows()
{
if (historyView.getSelectionModel().isEmpty())
historyView.getSelectionModel().selectAll();
String copied = historyView.getSelectionModel().getSelectedItems().stream().map(HistoryRow::getText).collect(Collectors.joining("\n"));
Clipboard.getSystemClipboard().setContent(Collections.singletonMap(DataFormat.PLAIN_TEXT, copied));
historyView.getSelectionModel().clearSelection();
}
| Clear the local variables.
|
public void clearVars()
{
localVars.clear();
if (textParser != null && frame.getProject() != null) {
textParser.newClassLoader(frame.getProject().getClassLoader());
}
}
|
| @see bluej.debugmgr.ValueCollection#getValueIterator()
|
public Iterator getValueIterator()
{
return localVars.iterator();
}
|
| @see bluej.debugmgr.ValueCollection#getNamedValue(java.lang.String)
|
public NamedValue getNamedValue(String name)
{
Class<Object> c = Object.class;
NamedValue nv = getLocalVar(name);
if (nv != null) {
return nv;
}
else {
return frame.getObjectBench().getNamedValue(name);
}
}
| Search for a named local variable, but do not fall back to the object
| bench if it cannot be found (return null in this case).
|
| @param name The name of the variable to search for
| @return The named variable, or null
|
private NamedValue getLocalVar(String name)
{
Iterator<CodepadVar> i = localVars.iterator();
while (i.hasNext()){
NamedValue nv = (NamedValue) i.next();
if (nv.getName().equals(name))
return nv;
}
return null;
}
private class CodePadResultWatcher
implements ResultWatcher
{
private final String command;
public CodePadResultWatcher(String command)
{
this.command = command;
}
|
| @see bluej.debugmgr.ResultWatcher#beginExecution()
|
@Override
@OnThread(Tag.FXPlatform)
public void beginCompile()
{
}
|
| @see bluej.debugmgr.ResultWatcher#beginExecution()
|
@Override
@OnThread(Tag.FXPlatform)
public void beginExecution(InvokerRecord ir)
{
BlueJEvent.raiseEvent(BlueJEvent.METHOD_CALL, ir);
}
|
| @see bluej.debugmgr.ResultWatcher#putResult(bluej.debugger.DebuggerObject, java.lang.String, bluej.testmgr.record.InvokerRecord)
|
@Override
@OnThread(Tag.FXPlatform)
public void putResult(final DebuggerObject result, final String name, final InvokerRecord ir)
{
frame.getObjectBench().addInteraction(ir);
updateInspectors();
if (newlyDeclareds != null)
{
Iterator<CodepadVar> i = newlyDeclareds.iterator();
while (i.hasNext())
{
CodepadVar cpv = (CodepadVar)i.next();
cpv.setInitialized();
}
newlyDeclareds = null;
}
boolean giveUninitializedWarning = autoInitializedVars != null && autoInitializedVars.size() != 0;
if (giveUninitializedWarning && Utility.firstTimeThisRun("TextEvalPane.uninitializedWarning"))
{
String warning = uninitializedWarning;
int findex = 0;
while (findex < warning.length())
{
int nindex = warning.indexOf('\n', findex);
if (nindex == -1)
nindex = warning.length();
String warnLine = warning.substring(findex, nindex);
error(warnLine);
findex = nindex + 1;
}
autoInitializedVars.clear();
}
if (!result.isNullObject())
{
DebuggerField resultField = result.getField(0);
String resultString = resultField.getValueString();
if (resultString.equals(nullLabel))
{
DataCollector.codePadSuccess(frame.getPackage(), ir.getOriginalCommand(), resultString);
output(resultString);
}
else
{
boolean isObject = resultField.isReferenceType();
if (isObject)
{
DebuggerObject resultObject = resultField.getValueObject(null);
String resultType = resultObject.getGenType().toString(true);
String resultOutputString = resultString + " (" + resultType + ")";
DataCollector.codePadSuccess(frame.getPackage(), ir.getOriginalCommand(), resultOutputString);
objectOutput(resultOutputString, new ObjectInfo(resultObject, ir));
}
else
{
String resultType = resultField.getType().toString(true);
String resultOutputString = resultString + " (" + resultType + ")";
DataCollector.codePadSuccess(frame.getPackage(), ir.getOriginalCommand(), resultOutputString);
output(resultOutputString);
}
}
}
else
{
}
ExecutionEvent executionEvent = new ExecutionEvent(frame.getPackage());
executionEvent.setCommand(command);
executionEvent.setResult(ExecutionEvent.NORMAL_EXIT);
executionEvent.setResultObject(result);
BlueJEvent.raiseEvent(BlueJEvent.EXECUTION_RESULT, executionEvent);
textParser.confirmCommand();
inputField.setEditable(true);
busy = false;
}
private void updateInspectors()
{
Project proj = frame.getPackage().getProject();
proj.updateInspectors();
}
| An invocation has failed - here is the error message
|
@Override
public void putError(String message, InvokerRecord ir)
{
if (firstTry)
{
if (wrappedResult)
{
wrappedResult = false;
errorMessage = null;
invoker = new Invoker(frame, CodePad.this, command, this);
invoker.setImports(textParser.getImportStatements());
invoker.doFreeFormInvocation("");
}
else
{
firstTry = false;
invoker = new Invoker(frame, CodePad.this, command, this);
invoker.setImports(textParser.getImportStatements());
invoker.doFreeFormInvocation(null);
if (errorMessage == null)
{
errorMessage = message;
}
}
}
else
{
if (errorMessage == null)
{
errorMessage = message;
}
if (autoInitializedVars != null)
{
autoInitializedVars.clear();
}
removeNewlyDeclareds();
DataCollector.codePadError(frame.getPackage(), ir.getOriginalCommand(), errorMessage);
showErrorMsg(errorMessage);
errorMessage = null;
}
}
| A runtime exception occurred.
|
@Override
public void putException(ExceptionDescription exception, InvokerRecord ir)
{
ExecutionEvent executionEvent = new ExecutionEvent(frame.getPackage());
executionEvent.setCommand(command);
executionEvent.setResult(ExecutionEvent.EXCEPTION_EXIT);
executionEvent.setException(exception);
BlueJEvent.raiseEvent(BlueJEvent.EXECUTION_RESULT, executionEvent);
updateInspectors();
if (autoInitializedVars != null)
{
autoInitializedVars.clear();
}
removeNewlyDeclareds();
String message = exception.getClassName() + " (" + exception.getText() + ")";
DataCollector.codePadException(frame.getPackage(), ir.getOriginalCommand(), message);
showExceptionMsg(message);
}
| The remote VM terminated before execution completed (or as a result of
| execution).
|
@Override
public void putVMTerminated(InvokerRecord ir)
{
if (autoInitializedVars != null)
autoInitializedVars.clear();
removeNewlyDeclareds();
String message = Config.getString("pkgmgr.codepad.vmTerminated");
DataCollector.codePadError(frame.getPackage(), ir.getOriginalCommand(), message);
error(message);
completeExecution();
}
}
| Remove the newly declared variables from the value collection.
| (This is needed if compilation fails, or execution bombs with an exception).
|
private void removeNewlyDeclareds()
{
if (newlyDeclareds != null) {
Iterator<CodepadVar> i = newlyDeclareds.iterator();
while (i.hasNext()){
localVars.remove(i.next());
}
newlyDeclareds = null;
}
}
| Show an error message, and allow further command input.
|
private void showErrorMsg(final String message)
{
error("Error: " + message);
completeExecution();
}
| Show an exception message, and allow further command input.
|
private void showExceptionMsg(final String message)
{
error("Exception: " + message);
completeExecution();
}
| Execution of the current command has finished (one way or another).
| Allow further command input.
|
private void completeExecution()
{
inputField.setEditable(true);
busy = false;
}
| Record part of a command
| @param s
|
private void command(String s, boolean isFinalLine)
{
addRow(new CommandRow(s, isFinalLine));
}
private void addRow(HistoryRow row)
{
historyView.getSelectionModel().clearSelection();
historyView.getItems().add(row);
historyView.scrollTo(historyView.getItems().size() - 1);
}
| Write a (non-error) message to the text area.
| @param s The message
|
private void output(String s)
{
addRow(new OutputSuccessRow(s, null));
}
| Write a (non-error) message to the text area.
| @param s The message
|
private void objectOutput(String s, ObjectInfo objInfo)
{
addRow(new OutputSuccessRow(s, objInfo));
}
| Write an error message to the text area.
| @param s The message
|
private void error(String s)
{
addRow(new ErrorRow(s));
}
public void clear()
{
clearVars();
}
| Clear the CodePad after closing the project that the only one is opened,
| When opening a new project, the CodePad appears again and it is clear.
|
public void clearHistoryView()
{
historyView.getItems().clear();
}
private void executeCommand(String command)
{
if (busy) {
return;
}
firstTry = true;
busy = true;
if (textParser == null) {
textParser = new TextAnalyzer(frame.getProject().getEntityResolver(),
frame.getPackage().getQualifiedName(), CodePad.this);
}
String retType;
retType = textParser.parseCommand(command);
wrappedResult = (retType != null && retType.length() != 0);
if (retType == null) {
firstTry = false;
command = textParser.getAmendedCommand();
List<DeclaredVar> declaredVars = textParser.getDeclaredVars();
if (declaredVars != null) {
Iterator<DeclaredVar> i = declaredVars.iterator();
while (i.hasNext()){
if (newlyDeclareds == null) {
newlyDeclareds = new ArrayList<CodepadVar>();
}
if (autoInitializedVars == null) {
autoInitializedVars = new ArrayList<String>();
}
DeclaredVar dv = i.next();
String declaredName = dv.getName();
if (getLocalVar(declaredName) != null) {
String errMsg = Config.getString("pkgmgr.codepad.redefinedVar");
errMsg = Utility.mergeStrings(errMsg, declaredName);
showErrorMsg(errMsg);
removeNewlyDeclareds();
return;
}
CodepadVar cpv = new CodepadVar(dv.getName(), dv.getDeclaredType(), dv.isFinal());
newlyDeclareds.add(cpv);
localVars.add(cpv);
if (! dv.isInitialized()) {
autoInitializedVars.add(dv.getName());
}
}
}
}
CodePadResultWatcher watcher = new CodePadResultWatcher(command);
invoker = new Invoker(frame, CodePad.this, command, watcher);
invoker.setImports(textParser.getImportStatements());
if (!invoker.doFreeFormInvocation(retType)) {
firstTry = false;
watcher.putError("Invocation failed.", null);
}
}
private void softReturn()
{
String line = inputField.getText();
if (line.trim().isEmpty())
return;
currentCommand += line + " ";
history.add(line);
command(line, false);
inputField.setText("");
}
private void historyBack()
{
String line = history.getPrevious();
if (line != null) {
setInput(line);
}
}
private void setInput(String line)
{
inputField.setText(line);
inputField.end();
}
private void historyForward()
{
String line = history.getNext();
if (line != null) {
setInput(line);
}
}
public void focusInputField()
{
inputField.requestFocus();
}
@OnThread(Tag.Any)
final class ObjectInfo
{
DebuggerObject obj;
InvokerRecord ir;
| Create an object holding information about an invocation.
|
public ObjectInfo(DebuggerObject obj, InvokerRecord ir)
{
this.obj = obj;
this.ir = ir;
}
}
final class CodepadVar
implements NamedValue {
String name;
boolean finalVar;
boolean initialized = false;
JavaType type;
public CodepadVar(String name, JavaType type, boolean finalVar)
{
this.name = name;
this.finalVar = finalVar;
this.type = type;
}
public String getName()
{
return name;
}
public JavaType getGenType()
{
return type;
}
public boolean isFinal()
{
return finalVar;
}
public boolean isInitialized()
{
return initialized;
}
public void setInitialized()
{
initialized = true;
}
}
}
top,
use,
map,
class CodePad
. @OnThread
top,
use,
map,
class CodePad . HistoryRow
. getPseudoClass
. RowStyle
. HistoryRow
. getText
. toString
. getGraphic
. getStyle
top,
use,
map,
abstract class CodePad . HistoryRow . IndentedRow
. IndentedRow
. getGraphic
top,
use,
map,
class CommandRow
. CommandRow
. getGraphic
. getStyle
top,
use,
map,
class OutputSuccessRow
. OutputSuccessRow
. getGraphic
. getStyle
top,
use,
map,
class ErrorRow
. ErrorRow
. getStyle
. CodePad
. onChanged
. updateItem
. copySelectedRows
. clearVars
. getValueIterator
. getNamedValue
. getLocalVar
top,
use,
map,
class CodePadResultWatcher
. CodePadResultWatcher
. beginCompile
. beginExecution
. putResult
. updateInspectors
. putError
. putException
. putVMTerminated
. removeNewlyDeclareds
. showErrorMsg
. showExceptionMsg
. completeExecution
. command
. addRow
. output
. objectOutput
. error
. clear
. clearHistoryView
. executeCommand
. softReturn
. historyBack
. setInput
. historyForward
. focusInputField
top,
use,
map,
class ObjectInfo
. ObjectInfo
top,
use,
map,
class CodepadVar
. CodepadVar
. getName
. getGenType
. isFinal
. isInitialized
. setInitialized
1223 neLoCode
+ 63 LoComm