Always diplay sad face on errors; use nullCheck() function; see https://github.com/Microsoft/pxt/issues/302

This commit is contained in:
Michal Moskal 2016-09-05 14:26:07 +01:00
parent 50293fc654
commit 61a29f7c67
4 changed files with 64 additions and 66 deletions

View File

@ -154,7 +154,7 @@ namespace pxsim.instructions {
//TODO: Refactor this function; it is too complicated. There is a lot of error-prone math being done //TODO: Refactor this function; it is too complicated. There is a lot of error-prone math being done
// to scale and place all elements which could be simplified with more forethought. // to scale and place all elements which could be simplified with more forethought.
let svgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg"); let svgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
let dims = {l: 0, t: 0, w: 0, h: 0}; let dims = { l: 0, t: 0, w: 0, h: 0 };
let cmpSvgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg"); let cmpSvgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
svgEl.appendChild(cmpSvgEl); svgEl.appendChild(cmpSvgEl);
@ -181,7 +181,7 @@ namespace pxsim.instructions {
scale(opts.cmpHeight / dims.h) scale(opts.cmpHeight / dims.h)
} }
svg.hydrate(cmpSvgEl, cmpSvgAtts); svg.hydrate(cmpSvgEl, cmpSvgAtts);
let elDims = {l: dims.l, t: dims.t, w: dims.w, h: dims.h}; let elDims = { l: dims.l, t: dims.t, w: dims.w, h: dims.h };
let updateL = (newL: number) => { let updateL = (newL: number) => {
if (newL < dims.l) { if (newL < dims.l) {
@ -293,7 +293,7 @@ namespace pxsim.instructions {
let cnstr = builtinComponentPartVisual[builtinVis]; let cnstr = builtinComponentPartVisual[builtinVis];
el = cnstr([0, 0]); el = cnstr([0, 0]);
} else { } else {
let partVis = <PartVisualDefinition> cmp; let partVis = <PartVisualDefinition>cmp;
el = visuals.mkGenericPartSVG(partVis); el = visuals.mkGenericPartSVG(partVis);
} }
return wrapSvg(el, opts); return wrapSvg(el, opts);
@ -320,7 +320,7 @@ namespace pxsim.instructions {
let step = w.assemblyStep + 1; let step = w.assemblyStep + 1;
(stepToWires[step] || (stepToWires[step] = [])).push(w) (stepToWires[step] || (stepToWires[step] = [])).push(w)
}); });
let getMaxStep = (ns: {assemblyStep: number}[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0); let getMaxStep = (ns: { assemblyStep: number }[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0);
let stepOffset = powerWires.length > 0 ? getMaxStep(powerWires) + 2 : 1; let stepOffset = powerWires.length > 0 ? getMaxStep(powerWires) + 2 : 1;
components.forEach(cAndWs => { components.forEach(cAndWs => {
let {component, wires} = cAndWs; let {component, wires} = cAndWs;
@ -364,10 +364,10 @@ namespace pxsim.instructions {
function mkBlankBoardAndBreadboard(boardDef: BoardDefinition, cmpDefs: Map<PartDefinition>, fnArgs: any, width: number, buildMode: boolean = false): visuals.BoardHost { function mkBlankBoardAndBreadboard(boardDef: BoardDefinition, cmpDefs: Map<PartDefinition>, fnArgs: any, width: number, buildMode: boolean = false): visuals.BoardHost {
let state = runtime.board as pxsim.DalBoard; let state = runtime.board as pxsim.DalBoard;
let boardHost = new visuals.BoardHost({ let boardHost = new visuals.BoardHost({
state: state, state: state,
boardDef: boardDef, boardDef: boardDef,
forceBreadboard: true, forceBreadboard: true,
cmpDefs: cmpDefs, cmpDefs: cmpDefs,
maxWidth: `${width}px`, maxWidth: `${width}px`,
fnArgs: fnArgs, fnArgs: fnArgs,
wireframe: buildMode, wireframe: buildMode,
@ -451,10 +451,10 @@ namespace pxsim.instructions {
// board and breadboard // board and breadboard
let boardImg = mkBoardImgSvg(props.boardDef.visual); let boardImg = mkBoardImgSvg(props.boardDef.visual);
let board = wrapSvg(boardImg, {left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BOARD_SCALE}); let board = wrapSvg(boardImg, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BOARD_SCALE });
panel.appendChild(board); panel.appendChild(board);
let bbRaw = mkBBSvg(); let bbRaw = mkBBSvg();
let bb = wrapSvg(bbRaw, {left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BB_SCALE}); let bb = wrapSvg(bbRaw, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BB_SCALE });
panel.appendChild(bb); panel.appendChild(bb);
// components // components
@ -591,8 +591,8 @@ namespace pxsim.instructions {
if (tsCode) { if (tsCode) {
//we use the docs renderer to decompile the code to blocks and render it //we use the docs renderer to decompile the code to blocks and render it
//TODO: render the blocks code directly //TODO: render the blocks code directly
let md = let md =
`\`\`\`blocks `\`\`\`blocks
${tsCode} ${tsCode}
\`\`\` \`\`\`
\`\`\`package \`\`\`package
@ -600,9 +600,9 @@ ${tsPackage}
\`\`\` \`\`\`
` `
pxtdocs.requireMarked = function() { return (<any>window).marked; } pxtdocs.requireMarked = function () { return (<any>window).marked; }
pxtrunner.renderMarkdownAsync(codeContainerDiv, md) pxtrunner.renderMarkdownAsync(codeContainerDiv, md)
.done(function() { .done(function () {
let codeSvg = $("#proj-code-container svg"); let codeSvg = $("#proj-code-container svg");
if (codeSvg.length > 0) { if (codeSvg.length > 0) {
//code rendered successfully as blocks //code rendered successfully as blocks

View File

@ -5,14 +5,33 @@
namespace pxsim { namespace pxsim {
export type BBRowCol = [/*row*/string, /*column*/string]; export type BBRowCol = [/*row*/string, /*column*/string];
export type BoardPin = string; export type BoardPin = string;
export interface BBLoc {type: "breadboard", rowCol: BBRowCol}; export interface BBLoc { type: "breadboard", rowCol: BBRowCol };
export interface BoardLoc {type: "dalboard", pin: BoardPin}; export interface BoardLoc { type: "dalboard", pin: BoardPin };
export type Loc = BBLoc | BoardLoc; export type Loc = BBLoc | BoardLoc;
export function initRuntimeWithDalBoard() { export function initRuntimeWithDalBoard() {
U.assert(!runtime.board); U.assert(!runtime.board);
let b = new DalBoard(); let b = new DalBoard();
runtime.board = b; runtime.board = b;
runtime.postError = (e) => {
led.setBrightness(255);
let img = board().ledMatrixState.image;
img.clear();
img.set(0, 4, 255);
img.set(1, 3, 255);
img.set(2, 3, 255);
img.set(3, 3, 255);
img.set(4, 4, 255);
img.set(0, 0, 255);
img.set(1, 0, 255);
img.set(0, 1, 255);
img.set(1, 1, 255);
img.set(3, 0, 255);
img.set(4, 0, 255);
img.set(3, 1, 255);
img.set(4, 1, 255);
runtime.updateDisplay();
}
} }
if (!pxsim.initCurrentRuntime) { if (!pxsim.initCurrentRuntime) {
pxsim.initCurrentRuntime = initRuntimeWithDalBoard; pxsim.initCurrentRuntime = initRuntimeWithDalBoard;
@ -50,15 +69,15 @@ namespace pxsim.visuals {
move: "pointermove", move: "pointermove",
leave: "pointerleave" leave: "pointerleave"
} : { } : {
up: "mouseup", up: "mouseup",
down: "mousedown", down: "mousedown",
move: "mousemove", move: "mousemove",
leave: "mouseleave" leave: "mouseleave"
}; };
export function translateEl(el: SVGElement, xy: [number, number]) { export function translateEl(el: SVGElement, xy: [number, number]) {
//TODO append translation instead of replacing the full transform //TODO append translation instead of replacing the full transform
svg.hydrate(el, {transform: `translate(${xy[0]} ${xy[1]})`}); svg.hydrate(el, { transform: `translate(${xy[0]} ${xy[1]})` });
} }
export interface ComposeOpts { export interface ComposeOpts {
@ -83,14 +102,14 @@ namespace pxsim.visuals {
export function composeSVG(opts: ComposeOpts): ComposeResult { export function composeSVG(opts: ComposeOpts): ComposeResult {
let [a, b] = [opts.el1, opts.el2]; let [a, b] = [opts.el1, opts.el2];
U.assert(a.x == 0 && a.y == 0 && b.x == 0 && b.y == 0, "el1 and el2 x,y offsets not supported"); U.assert(a.x == 0 && a.y == 0 && b.x == 0 && b.y == 0, "el1 and el2 x,y offsets not supported");
let setXY = (e: SVGSVGElement, x: number, y: number) => svg.hydrate(e, {x: x, y: y}); let setXY = (e: SVGSVGElement, x: number, y: number) => svg.hydrate(e, { x: x, y: y });
let setWH = (e: SVGSVGElement, w: string, h: string) => { let setWH = (e: SVGSVGElement, w: string, h: string) => {
if (w) if (w)
svg.hydrate(e, {width: w}); svg.hydrate(e, { width: w });
if (h) if (h)
svg.hydrate(e, {height: h}); svg.hydrate(e, { height: h });
} }
let setWHpx = (e: SVGSVGElement, w: number, h: number) => svg.hydrate(e, {width: `${w}px`, height: `${h}px`}); let setWHpx = (e: SVGSVGElement, w: number, h: number) => svg.hydrate(e, { width: `${w}px`, height: `${h}px` });
let scaleUnit = opts.scaleUnit2; let scaleUnit = opts.scaleUnit2;
let aScalar = opts.scaleUnit2 / opts.scaleUnit1; let aScalar = opts.scaleUnit2 / opts.scaleUnit1;
let bScalar = 1.0; let bScalar = 1.0;
@ -157,11 +176,11 @@ namespace pxsim.visuals {
let w = scaleFn(opts.width); let w = scaleFn(opts.width);
let h = scaleFn(opts.height); let h = scaleFn(opts.height);
let img = <SVGImageElement>svg.elt("image", { let img = <SVGImageElement>svg.elt("image", {
width: w, width: w,
height: h, height: h,
"href": `${opts.image}` "href": `${opts.image}`
}); });
return {el: img, w: w, h: h, x: 0, y: 0}; return { el: img, w: w, h: h, x: 0, y: 0 };
} }
export type Coord = [number, number]; export type Coord = [number, number];
@ -190,13 +209,15 @@ namespace pxsim.visuals {
export function mkTxt(cx: number, cy: number, size: number, rot: number, txt: string, txtXOffFactor?: number, txtYOffFactor?: number): SVGTextElement { export function mkTxt(cx: number, cy: number, size: number, rot: number, txt: string, txtXOffFactor?: number, txtYOffFactor?: number): SVGTextElement {
let el = <SVGTextElement>svg.elt("text") let el = <SVGTextElement>svg.elt("text")
//HACK: these constants (txtXOffFactor, txtYOffFactor) tweak the way this algorithm knows how to center the text //HACK: these constants (txtXOffFactor, txtYOffFactor) tweak the way this algorithm knows how to center the text
txtXOffFactor = txtXOffFactor || -0.33333; txtXOffFactor = txtXOffFactor || -0.33333;
txtYOffFactor = txtYOffFactor || 0.3; txtYOffFactor = txtYOffFactor || 0.3;
const xOff = txtXOffFactor * size * txt.length; const xOff = txtXOffFactor * size * txt.length;
const yOff = txtYOffFactor * size; const yOff = txtYOffFactor * size;
svg.hydrate(el, {style: `font-size:${size}px;`, svg.hydrate(el, {
transform: `translate(${cx} ${cy}) rotate(${rot}) translate(${xOff} ${yOff})` }); style: `font-size:${size}px;`,
transform: `translate(${cx} ${cy}) rotate(${rot}) translate(${xOff} ${yOff})`
});
svg.addClass(el, "noselect"); svg.addClass(el, "noselect");
el.textContent = txt; el.textContent = txt;
return el; return el;

View File

@ -195,26 +195,24 @@ namespace pxsim.images {
namespace pxsim.ImageMethods { namespace pxsim.ImageMethods {
export function showImage(leds: Image, offset: number) { export function showImage(leds: Image, offset: number) {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(leds)
leds.copyTo(offset, 5, board().ledMatrixState.image, 0) leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
runtime.queueDisplayUpdate() runtime.queueDisplayUpdate()
} }
export function plotImage(leds: Image, offset: number): void { export function plotImage(leds: Image, offset: number): void {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(leds)
leds.copyTo(offset, 5, board().ledMatrixState.image, 0) leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
runtime.queueDisplayUpdate() runtime.queueDisplayUpdate()
} }
export function height(leds: Image): number { export function height(leds: Image): number {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(leds)
return Image.height; return Image.height;
} }
export function width(leds: Image): number { export function width(leds: Image): number {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(leds)
return leds.width; return leds.width;
} }
@ -227,35 +225,32 @@ namespace pxsim.ImageMethods {
} }
export function pixel(leds: Image, x: number, y: number): number { export function pixel(leds: Image, x: number, y: number): number {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(leds)
return leds.get(x, y); return leds.get(x, y);
} }
export function setPixel(leds: Image, x: number, y: number, v: number) { export function setPixel(leds: Image, x: number, y: number, v: number) {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(leds)
leds.set(x, y, v); leds.set(x, y, v);
} }
export function clear(leds: Image) { export function clear(leds: Image) {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(leds)
leds.clear(); leds.clear();
} }
export function setPixelBrightness(i: Image, x: number, y: number, b: number) { export function setPixelBrightness(i: Image, x: number, y: number, b: number) {
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(i)
i.set(x, y, b); i.set(x, y, b);
} }
export function pixelBrightness(i: Image, x: number, y: number): number { export function pixelBrightness(i: Image, x: number, y: number): number {
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(i)
return i.get(x, y); return i.get(x, y);
} }
export function scrollImage(leds: Image, stride: number, interval: number): void { export function scrollImage(leds: Image, stride: number, interval: number): void {
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); pxtrt.nullCheck(leds)
if (stride == 0) stride = 1; if (stride == 0) stride = 1;
let cb = getResume(); let cb = getResume();

View File

@ -19,24 +19,6 @@ namespace pxsim {
export function panic(code: number) { export function panic(code: number) {
console.log("PANIC:", code) console.log("PANIC:", code)
led.setBrightness(255);
let img = board().ledMatrixState.image;
img.clear();
img.set(0, 4, 255);
img.set(1, 3, 255);
img.set(2, 3, 255);
img.set(3, 3, 255);
img.set(4, 4, 255);
img.set(0, 0, 255);
img.set(1, 0, 255);
img.set(0, 1, 255);
img.set(1, 1, 255);
img.set(3, 0, 255);
img.set(4, 0, 255);
img.set(3, 1, 255);
img.set(4, 1, 255);
runtime.updateDisplay();
throw new Error("PANIC " + code) throw new Error("PANIC " + code)
} }