package net.cakenet.jsaton.ui.tools.script;
import net.cakenet.jsaton.script.Script;
import net.cakenet.jsaton.script.ScriptState;
import net.cakenet.jsaton.script.debug.BreakType;
import net.cakenet.jsaton.script.debug.Breakpoint;
import net.cakenet.jsaton.script.debug.DebugFrame;
import net.cakenet.jsaton.ui.tools.ToolWindow;
import net.cakenet.jsaton.util.ImageUtil;
import org.fife.ui.rsyntaxtextarea.ErrorStrip;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rtextarea.GutterIconInfo;
import javax.swing.*;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class ScriptEditor extends ToolWindow implements PropertyChangeListener, BreakpointModificationListener {
private JPanel panel1;
public ScriptScrollPane scrollPane;
public ScriptEditorPane scriptPane;
public final Script script;
public ScriptEditor(final Script script) {
super(script.getName());
panel1 = new JPanel(new BorderLayout());
this.script = script;
script.addPropertyChangeListener(this);
scriptPane = ScriptEditorPane.paneFor(script, this);
scrollPane = new ScriptScrollPane(scriptPane);
scriptPane.setSyntaxEditingStyle(RSyntaxTextArea.SYNTAX_STYLE_RUBY);
scriptPane.setCodeFoldingEnabled(true);
scriptPane.setAntiAliasingEnabled(true);
scrollPane.setLineNumbersEnabled(false);
scrollPane.setBreakpointsEditable(true);
scrollPane.setBreakpointsEnabled(true);
scrollPane.addBreakpointModificationListener(this);
scrollPane.setLineNumbersEnabled(true);
panel1.add(scrollPane);
scriptPane.setText(script.getScript());
scriptPane.setDirty(false);
ErrorStrip es = scriptPane.getErrorStrip();
if (es != null)
panel1.add(es, BorderLayout.LINE_END);
// Update breakpoints...
for(int line: script.breakpoints.descendingKeySet()) {
scrollPane.addBreakpoint(line);
}
}
public void updateScript() {
java.util.List<GutterIconInfo> breakpointInfo = scrollPane.getBreakpoints();
synchronized (script.breakpoints) {
script.breakpoints.clear();
try {
for (GutterIconInfo b : breakpointInfo)
script.breakpoints.put(scriptPane.getLineOfOffset(b.getMarkedOffset()), new Breakpoint(BreakType.SUSPEND));
} catch (Exception e) {
e.printStackTrace();
}
}
}
public String getTitle() {
return script.getName();
}
public Component getContents() {
return panel1;
}
public Icon getIcon() {
return ImageUtil.loadIcon("icons/script.png");
}
private Color breakpointHighlightColor = new Color(0xff, 0, 0, 0x7f);
private int originalCaret = -1;
private Object highlightKey;
public boolean removeBreakpoint(int line) {
return scrollPane.removeBreakpoint(line);
}
public void propertyChange(PropertyChangeEvent pce) {
if (scriptPane == null)
return;
if (pce.getPropertyName().equals("state")) {
try {
Script source = (Script) pce.getSource();
if (source.getState() == ScriptState.RUNNING && originalCaret == -1) {
scriptPane.setEditable(false);
scriptPane.setHighlightCurrentLine(false);
originalCaret = scriptPane.getCaretPosition();
scriptPane.getCaret().setVisible(false);
scriptPane.getCaret().setSelectionVisible(false);
} else if (source.getState() == ScriptState.STOPPED) {
scriptPane.setHighlightCurrentLine(true);
unhighlightLastHighlightedBreakpoint();
scriptPane.setCaretPosition(originalCaret);
originalCaret = -1;
scriptPane.setEditable(true);
scriptPane.getCaret().setVisible(true);
scriptPane.getCaret().setSelectionVisible(true);
}
} catch (Exception e) {
/* Supress errors from the component (some bugs...)*/
}
} else if(pce.getPropertyName().equals("name")) {
setTitle(script.getName());
}
}
public boolean addBreakpoint(int line) {
return scrollPane.addBreakpoint(line);
}
public void unhighlightLastHighlightedBreakpoint() {
if (highlightKey != null) {
scriptPane.removeLineHighlight(highlightKey);
highlightKey = null;
}
}
public void highlightBreakpoint(DebugFrame frame) {
int line = frame.line - 1;
try {
unhighlightLastHighlightedBreakpoint();
if (line != -1) {
highlightKey = scriptPane.addLineHighlight(line, breakpointHighlightColor);
scriptPane.setCaretPosition(scriptPane.getLineStartOffset(line));
}
} catch (Exception e) {
/**/
}
}
public void breakpointAdded(int line) {
if (script.getState() == ScriptState.STOPPED)
return;
synchronized (script.breakpoints) {
script.breakpoints.put(line, new Breakpoint(BreakType.SUSPEND));
}
}
public void breakpointRemoved(int line) {
if (script.getState() == ScriptState.STOPPED)
return;
synchronized (script.breakpoints) {
script.breakpoints.remove(line);
}
}
public boolean isCloseable() {
return true;
}
public boolean isPinnable() {
return false;
}
public boolean hasTitlebar() {
return false;
}
}