@@ -3,27 +3,23 @@
3'use strict';
3'use strict';
5Elm.Debugger = null;
5Elm.Debugger = null;
6−Elm.debuggerInit = function(module) {
6+Elm.debuggerAttach = function(module) {
8 make: function(runtime) {
8 make: function(runtime) {
9− Elm.Debugger = debuggerInit(module, runtime);
9+ var wrappedModule = debugModule(module, runtime);
10+ Elm.debuggerInit = function() {
11+ Elm.Debugger = debuggerInit(wrappedModule, runtime);
10− return Elm.Debugger.moduleInstance;
13+ return wrappedModule.moduleInstance;
15−function debuggerInit(module, runtime) {
18+function debugModule(module, runtime) {
17 var programPaused = false;
19 var programPaused = false;
20 var recordedEvents = [];
20 var recordedEvents = [];
21 var eventCounter = 0;
21 var eventCounter = 0;
22 var asyncTimers = [];
22 var asyncTimers = [];
23− var initialProgramState = {
28 function wrapNotify(id, v) {
24 function wrapNotify(id, v) {
29 var timestep = Date.now();
25 var timestep = Date.now();
@@ -51,24 +47,131 @@ function debuggerInit(module, runtime) {
51 recordedEvents.push({ id:id, value:v, timestep:timestep });
47 recordedEvents.push({ id:id, value:v, timestep:timestep });
50+ function clearAsyncEvents() {
51+ asyncTimers.forEach(function(timer) {
52+ clearTimeout(timer.timerId);
56+ function clearRecordedEvents() {
60+ function getRecordedEvents() {
61+ return recordedEvents.slice();
64+ function setPaused(v) {
68+ function getPaused() {
69+ return programPaused;
72+ var wrappedRuntime = {
74+ runDelayed: wrapRunDelayed,
76+ display: runtime.display,
78+ addListener: runtime.addListener,
79+ inputs: runtime.inputs
82+ var moduleInstance = module.make(wrappedRuntime);
83+ var moduleNodes = flattenNodes(wrappedRuntime.inputs);
86+ moduleInstance: moduleInstance,
87+ moduleNodes: moduleNodes,
88+ initialNodeValues: saveNodeValues(moduleNodes),
89+ initialAsyncTimers: asyncTimers.slice(),
91+ clearAsyncEvents: clearAsyncEvents,
92+ clearRecordedEvents: clearRecordedEvents,
93+ getRecordedEvents: getRecordedEvents,
94+ getPaused: getPaused,
99+function debuggerInit(debugModule, runtime) {
100+ var Signal = Elm.Signal.make(runtime);
101+ var List = Elm.List.make(runtime);
102+ var graphicsNode = debugModule.moduleInstance.main.kids[0];
104+ var tracePathCanvas = document.createElement('canvas');
105+ tracePathCanvas.width = window.innerWidth;
106+ tracePathCanvas.height = window.innerHeight;
107+ tracePathCanvas.style.position = "absolute";
108+ tracePathCanvas.style.top = "0";
109+ tracePathCanvas.style.left = "0";
110+ runtime.node.parentNode.appendChild(tracePathCanvas);
112+ function graphicsUpdate(currentScene) {
113+ var ctx = tracePathCanvas.getContext('2d');
114+ ctx.clearRect(0, 0, tracePathCanvas.width, tracePathCanvas.height);
115+ ctx.fillText("Debugger trace path", 20, 20);
117+ function drawElement(elem) {
118+ if (elem.element.ctor == "Custom" && elem.element.type == "Collage")
120+ List.map(drawForm)(elem.element.model.forms);
122+ else if (elem.element.ctor == "Image")
127+ ctx.arc(x, y, 2, 0, 2*Math.PI);
128+ ctx.fillStyle = "grey";
131+ ctx.strokeStype = "black";
136+ function drawForm(form) {
138+ ctx.scale(form.scale, form.scale);
139+ ctx.rotate(form.theta);
140+ ctx.translate(form.x, -form.y);
141+ if (form.form.ctor == "FElement")
143+ drawElement(form.form._0);
150+ ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
151+ drawElement(currentScene);
155+ var tracePathNode = A2(Signal.lift, graphicsUpdate, graphicsNode);
54 function resetProgram() {
157 function resetProgram() {
55− clearAsyncEvents();
158+ debugModule.clearAsyncEvents();
56− restoreNodeValues(allNodes, initialProgramState.nodeValues);
159+ restoreNodeValues(debugModule.moduleNodes, debugModule.initialNodeValues);
57 redrawGraphics();
160 redrawGraphics();
60 function restartProgram() {
163 function restartProgram() {
61 resetProgram();
164 resetProgram();
62− recordedEvents = [];
165+ debugModule.clearRecordedEvents();
63− initialProgramState.asyncTimers.forEach(function(timer) {
166+ debugModule.initialAsyncTimers.forEach(function(timer) {
64 var func = timer.func;
167 var func = timer.func;
69 function stepTo(index) {
172 function stepTo(index) {
70− if (!programPaused) {
173+ if (!debugModule.getPaused()) {
71− programPaused = true;
174+ debugModule.setPaused(true);
72 resetProgram();
175 resetProgram();
@@ -95,12 +198,6 @@ function debuggerInit(module, runtime) {
95 return recordedEvents.length - 1;
198 return recordedEvents.length - 1;
98− function clearAsyncEvents() {
99− asyncTimers.forEach(function(timer) {
100− clearTimeout(timer.timerId);
104 function doPlayback(eventList) {
201 function doPlayback(eventList) {
105 var x = eventList.shift();
202 var x = eventList.shift();
106 var time = x[2];
203 var time = x[2];
@@ -113,38 +210,18 @@ function debuggerInit(module, runtime) {
115 function redrawGraphics() {
212 function redrawGraphics() {
116− var graphicsFoldp = moduleInstance.main.kids[0];
117− graphicsFoldp.recv(Date.now(), true, moduleInstance.main.id);
213+ graphicsNode.recv(Date.now(), true, debugModule.moduleInstance.main.id);
120− var wrappedRuntime = {
122− runDelayed: wrapRunDelayed,
124− display: runtime.display,
126− addListener: runtime.addListener,
127− inputs: runtime.inputs
130− var moduleInstance = module.make(wrappedRuntime);
132 var elmDebugger = {
216 var elmDebugger = {
133− moduleInstance: moduleInstance,
135− // debugger functions
136− reset: resetProgram,
217+ reset: resetProgram,
137− restart: restartProgram,
218+ restart: restartProgram,
138− getMaxSteps: getMaxSteps,
219+ getMaxSteps: getMaxSteps,
139− stepTo: stepTo
220+ stepTo: stepTo
142− allNodes = flattenNodes(wrappedRuntime.inputs);
143− initialProgramState.nodeValues = saveNodeValues(allNodes);
144− initialProgramState.asyncTimers = asyncTimers.slice();
146 return elmDebugger;
223 return elmDebugger;