package com.aicontest.visualizer;
import java.applet.Applet;
import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.swing.event.MouseInputListener;
import netscape.javascript.JSObject;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import com.aicontest.visualizer.js.dom.DOMWindow;
import com.aicontest.visualizer.js.dom.HTMLCanvasElement;
import com.aicontest.visualizer.js.tasks.EventExecutionUnit;
public class Visualizer extends WebWrapper implements MouseInputListener,
KeyListener, ComponentListener {
private Image offscreen;
private Graphics offscreenGraphics;
private final DOMWindow domWindow;
private final VisualizerPanel drawPanel;
private final IVisualizerUser app;
private JSObject jsRoot;
public Visualizer(IVisualizerUser app, int width, int height,
boolean resizable) throws InstantiationException,
IllegalAccessException, IOException {
super(app.getJavaScriptPath());
this.app = app;
domWindow = new DOMWindow("Visualizer", this);
Object window = Context.javaToJS(domWindow, global);
ScriptableObject.putProperty(global, "window", window);
Object document = Context.javaToJS(domWindow.getDocument(), global);
ScriptableObject.putProperty(global, "document", document);
loadProgram(app.getProgram());
runProgram();
drawPanel = new VisualizerPanel(this, width, height);
drawPanel.addComponentListener(this);
drawPanel.addMouseMotionListener(this);
drawPanel.addMouseListener(this);
drawPanel.addKeyListener(this);
app.setVisualizerPanel(drawPanel, resizable);
}
public synchronized void paint(Graphics g) {
g.drawImage(offscreen, 0, 0, null);
Toolkit.getDefaultToolkit().sync();
}
@Override
protected synchronized void postExecute() {
if ((canvas != null) && (canvas.getContext("2d").isDrawn())) {
BufferedImage pixmap = canvas.getPixmap();
offscreenGraphics.drawImage(pixmap, 0, 0, null);
drawPanel.repaint();
}
}
public void setCanvas(HTMLCanvasElement canvas) {
this.canvas = canvas;
canvasResized();
}
public synchronized void canvasResized() {
if (canvas != null
&& canvas.getWidth() > 0
&& canvas.getHeight() > 0
&& (offscreen == null
|| offscreen.getWidth(drawPanel) != canvas.getWidth() || offscreen
.getHeight(drawPanel) != canvas.getHeight())) {
offscreen = drawPanel.createImage(canvas.getWidth(),
canvas.getHeight());
if (offscreen != null) {
offscreenGraphics = offscreen.getGraphics();
}
}
}
public VisualizerPanel getDrawPanel() {
return drawPanel;
}
public DOMWindow getDomWindow() {
return domWindow;
}
public Container getContainer() {
Component result = drawPanel;
while ((!(result instanceof Frame)) && (!(result instanceof Applet))) {
result = result.getParent();
}
return (Container) result;
}
protected EventExecutionUnit createEventObject(InputEvent e, String type) {
EventExecutionUnit task = null;
if (canvas != null) {
Scriptable event = cx.newObject(global);
event.put("type", event, type);
event.put("altKey", event, Boolean.valueOf(e.isAltDown()));
event.put("ctrlKey", event, Boolean.valueOf(e.isControlDown()));
event.put("shiftKey", event, Boolean.valueOf(e.isShiftDown()));
event.put("button", event,
Integer.valueOf(e.getModifiersEx() >> 10 & 0x7));
if ((e instanceof MouseEvent)) {
MouseEvent me = (MouseEvent) e;
event.put("clientX", event, Integer.valueOf(me.getX()));
event.put("clientY", event, Integer.valueOf(me.getY()));
event.put("layerX", event, Integer.valueOf(me.getX()));
event.put("layerY", event, Integer.valueOf(me.getY()));
event.put("offsetX", event, Integer.valueOf(me.getX()));
event.put("offsetY", event, Integer.valueOf(me.getY()));
event.put("pageX", event, Integer.valueOf(me.getX()));
event.put("pageY", event, Integer.valueOf(me.getY()));
event.put("screenX", event, Integer.valueOf(me.getXOnScreen()));
event.put("screenY", event, Integer.valueOf(me.getYOnScreen()));
event.put("x", event, Integer.valueOf(me.getX()));
event.put("y", event, Integer.valueOf(me.getY()));
switch (me.getButton()) {
case 2:
event.put("which", event, Integer.valueOf(3));
break;
case 3:
event.put("which", event, Integer.valueOf(2));
break;
default:
event.put("which", event, Integer.valueOf(me.getButton()));
}
task = new EventExecutionUnit(canvas, "on" + type,
new Object[] { event });
} else if ((e instanceof KeyEvent)) {
KeyEvent ke = (KeyEvent) e;
event.put("keyCode", event, Integer.valueOf(ke.getKeyCode()));
event.put("which", event, Integer.valueOf(ke.getKeyChar()));
task = new EventExecutionUnit(domWindow.getDocument(), "on"
+ type, new Object[] { event });
}
addTask(task);
e.consume();
}
return task;
}
public boolean setFullscreen(boolean enable) {
return app.setFullScreen(enable);
}
@Override
public void keyPressed(KeyEvent e) {
createEventObject(e, "keydown");
}
@Override
public void keyReleased(KeyEvent e) {
createEventObject(e, "keyup");
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
createEventObject(e, "mouseout");
}
@Override
public void mousePressed(MouseEvent e) {
createEventObject(e, "mousedown");
}
@Override
public void mouseReleased(MouseEvent e) {
createEventObject(e, "mouseup");
}
@Override
public void mouseDragged(MouseEvent e) {
mouseMoved(e);
}
@Override
public void mouseMoved(MouseEvent e) {
EventExecutionUnit task = createEventObject(e, "mousemove");
if (task != null) {
addCompressedEventTask(task);
}
}
@Override
public void componentHidden(ComponentEvent e) {
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentResized(ComponentEvent e) {
addCompressedEventTask(new EventExecutionUnit(domWindow, "onresize",
ScriptRuntime.emptyArgs));
}
@Override
public void componentShown(ComponentEvent e) {
}
public void setJsRoot(JSObject jsRoot) {
this.jsRoot = jsRoot;
}
public JSObject getJsRoot() {
return jsRoot;
}
}