git @ Cat's Eye Technologies yoob.js / a5d37fc
Tape contains Cursor list, does not contain View stuff. Untested. Chris Pressey 9 years ago
4 changed file(s) with 180 addition(s) and 70 deletion(s). Raw diff Collapse all Expand all
2121 this.pf = cfg.playfield;
2222 this.canvas = cfg.canvas;
2323 this.ctx = this.canvas.getContext('2d');
24 this.cursors = cfg.cursors || [];
2524 this.fixedPosition = !!cfg.fixedPosition;
2625 this.fixedSizeCanvas = !!cfg.fixedSizeCanvas;
2726 this.drawCursorsFirst = (cfg.drawCursorsFirst === undefined) ? true : !!cfg.drawCursorsFirst;
120119 */
121120 this.draw = function() {
122121 var canvas = this.canvas;
123 var ctx = canvas.getContext('2d');
124122 var cellWidth = this.cellWidth;
125123 var cellHeight = this.cellHeight;
126124
129127
130128 canvas.width = width * cellWidth;
131129 canvas.height = height * cellHeight;
130 this.ctx = canvas.getContext('2d');
131 var ctx = this.ctx;
132132
133 this.ctx.textBaseline = "top";
134 this.ctx.font = cellHeight + "px monospace";
133 ctx.textBaseline = "top";
134 ctx.font = cellHeight + "px monospace";
135135
136136 var offsetX = 0;
137137 var offsetY = 0;
0 /*
1 * This file is part of yoob.js version 0.11-PRE
2 * Available from https://github.com/catseye/yoob.js/
3 * This file is in the public domain. See http://unlicense.org/ for details.
4 */
5 if (window.yoob === undefined) yoob = {};
6
7 /*
8 * A view (in the MVC sense) for depicting a yoob.Tape (-compatible)
9 * object on an HTML5 <canvas> element (or compatible object).
10 *
11 * drawCursorsFirst defaults to true. This produces the pleasing visual
12 * effect of the cursor being behind the cell values, but only if the cell values
13 * themselves have transparent areas (e.g. if they're glyphs in some font.)
14 * If the cell values are solid and fill the entire cell, drawCursorsFirst: false
15 * may be in order.
16 */
17 yoob.TapeCanvasView = function() {
18 this.init = function(cfg) {
19 this.tape = cfg.tape;
20 this.canvas = cfg.canvas;
21 this.ctx = this.canvas.getContext('2d');
22 this.fixedPosition = !!cfg.fixedPosition;
23 this.fixedSizeCanvas = !!cfg.fixedSizeCanvas;
24 this.drawCursorsFirst = (cfg.drawCursorsFirst === undefined) ? true : !!cfg.drawCursorsFirst;
25 this.setCellDimensions(cfg.cellWidth || 8, cfg.cellHeight || 8);
26 return this;
27 };
28
29 /*** Chainable setters ***/
30
31 this.setTape = function(tape) {
32 this.tape = tape;
33 return this;
34 };
35
36 this.setCanvas = function(element) {
37 this.canvas = element;
38 this.ctx = this.canvas.getContext('2d');
39 return this;
40 };
41
42 /*
43 * Set the displayed dimensions of every cell.
44 * cellWidth and cellHeight are canvas units of measure for each cell.
45 * If cellWidth is undefined, the width of a character in the monospace
46 * font of cellHeight pixels is used.
47 */
48 this.setCellDimensions = function(cellWidth, cellHeight) {
49 this.ctx.textBaseline = "top";
50 this.ctx.font = cellHeight + "px monospace";
51
52 if (cellWidth === undefined) {
53 cellWidth = this.ctx.measureText("@").width;
54 }
55
56 this.cellWidth = cellWidth;
57 this.cellHeight = cellHeight;
58 return this;
59 };
60
61 /*
62 * Draws cells of the Tape in a drawing context.
63 * cellWidth and cellHeight are canvas units of measure.
64 *
65 * The default implementation tries to call a .draw() method on the cell's
66 * value, if one exists, and just renders it as text, in black, if not.
67 *
68 * Override if you wish to draw elements in some other way.
69 */
70 this.drawCell = function(ctx, value, pos,
71 canvasX, canvasY, cellWidth, cellHeight) {
72 if (value.draw !== undefined) {
73 value.draw(ctx, pos, canvasX, canvasY,
74 cellWidth, cellHeight);
75 } else {
76 ctx.fillStyle = "black";
77 ctx.fillText(value.toString(), canvasX, canvasY);
78 }
79 };
80
81 /*
82 * Draws the Tape in a drawing context.
83 * cellWidth and cellHeight are canvas units of measure for each cell.
84 * offsetX and offsetY are canvas units of measure for the top-left
85 * of the entire playfield.
86 */
87 this.drawContext = function(ctx, offsetX, offsetY, cellWidth, cellHeight) {
88 var $this = this;
89 this.tape.foreach(function (pos, value) {
90 $this.drawCell(ctx, value, pos,
91 offsetX + pos * cellWidth, offsetY,
92 cellWidth, cellHeight);
93 });
94 };
95
96 /*
97 * Override if you like.
98 */
99 this.drawCursor = function(ctx, cursor, canvasX, canvasY, cellWidth, cellHeight) {
100 ctx.fillStyle = this.cursorFillStyle || "#50ff50";
101 ctx.fillRect(canvasX, canvasY, cellWidth, cellHeight);
102 };
103
104 this.drawCursors = function(ctx, offsetX, offsetY, cellWidth, cellHeight) {
105 var cursors = this.tape.cursors;
106 for (var i = 0; i < cursors.length; i++) {
107 var cursor = cursors[i];
108 this.drawCursor(ctx, cursor,
109 offsetX + cursor.getX() * cellWidth, offsetY,
110 cellWidth, cellHeight);
111 }
112 };
113
114 /*
115 * Draw the Tape, and its set of Cursors, on the canvas element.
116 * Resizes the canvas to the needed dimensions first.
117 */
118 this.draw = function() {
119 var canvas = this.canvas;
120 var cellWidth = this.cellWidth;
121 var cellHeight = this.cellHeight;
122
123 var width = this.tape.getCursoredExtent(); // this.max - this.min + 1;
124 var height = 1;
125
126 canvas.width = width * cellWidth;
127 canvas.height = height * cellHeight;
128 this.ctx = canvas.getContext('2d');
129 var ctx = this.ctx;
130
131 ctx.textBaseline = "top";
132 ctx.font = cellHeight + "px monospace";
133
134 if (cellWidth === undefined) {
135 cellWidth = ctx.measureText("@").width;
136 }
137
138 var offsetX = 0; // this.min * cellWidth * -1;
139 var offsetY = 0;
140
141 /*
142 if (!this.fixedPosition) {
143 offsetX = (this.pf.getLowerX() || 0) * cellWidth * -1;
144 offsetY = (this.pf.getLowerY() || 0) * cellHeight * -1;
145 }
146 */
147
148 if (this.drawCursorsFirst) {
149 this.drawCursors(ctx, offsetX, offsetY, cellWidth, cellHeight);
150 }
151
152 this.drawContext(ctx, offsetX, offsetY, cellWidth, cellHeight);
153
154 if (!this.drawCursorsFirst) {
155 this.drawCursors(ctx, offsetX, offsetY, cellWidth, cellHeight);
156 }
157 };
158 };
3939 };
4040
4141 /*
42 * Override if you like.
43 */
44 this.wrapCursorText = function(cursor, text) {
45 var fillStyle = this.cursorFillStyle || "#50ff50";
46 return '<span style="background: ' + fillStyle + '">' +
47 text + '</span>';
48 };
49
50 /*
4251 * Render the Tape, as HTML, on the DOM element.
4352 * TODO: make this not awful.
4453 */
4554 this.draw = function() {
55 var cursors = this.tape.cursors;
4656 var text = "";
4757 this.tape.foreach(function(pos, value) {
48 text += this.render(value) + "<br/>";
58 var rendered = this.render(value);
59 for (var i = 0; i < cursors.length; i++) {
60 if (cursors[i].x === x && cursors[i].y === y) {
61 rendered = this.wrapCursorText(cursors[i], rendered);
62 }
63 }
64 text += rendered + "<br/>";
4965 }, { dense: true });
5066 this.element.innerHTML = text;
5167 };
8989 this.put(cursor.getX(), value);
9090 return this;
9191 };
92
93 /*
94 * Draws elements of the Tape in a drawing context.
95 * x and y are canvas coordinates, and width and height
96 * are canvas units of measure.
97 * The default implementation just renders them as text,
98 * in black.
99 * Override if you wish to draw them differently.
100 */
101 this.drawElement = function(ctx, x, y, cellWidth, cellHeight, elem) {
102 ctx.fillStyle = "black";
103 ctx.fillText(elem.toString(), x, y);
104 };
105
106 /*
107 * Draws the Tape in a drawing context.
108 * cellWidth and cellHeight are canvas units of measure for each cell.
109 */
110 this.drawContext = function(ctx, offsetX, offsetY, cellWidth, cellHeight) {
111 var $this = this;
112 this.foreach(function (pos, elem) {
113 $this.drawElement(ctx, offsetX + pos * cellWidth, offsetY,
114 cellWidth, cellHeight, elem);
115 });
116 };
117
118 /*
119 * Draws the Tape, and a set of TapeHeads, on a canvas element.
120 * Resizes the canvas to the needed dimensions.
121 * cellWidth and cellHeight are canvas units of measure for each cell.
122 */
123 this.drawCanvas = function(canvas, cellWidth, cellHeight, heads) {
124 var ctx = canvas.getContext('2d');
125
126 var width = this.max - this.min + 1;
127 var height = 1;
128
129 if (cellWidth === undefined) {
130 ctx.textBaseline = "top";
131 ctx.font = cellHeight + "px monospace";
132 cellWidth = ctx.measureText("@").width;
133 }
134
135 canvas.width = width * cellWidth;
136 canvas.height = height * cellHeight;
137
138 ctx.clearRect(0, 0, canvas.width, canvas.height);
139
140 ctx.textBaseline = "top";
141 ctx.font = cellHeight + "px monospace";
142
143 var offsetX = this.min * cellWidth * -1;
144 var offsetY = 0;
145
146 for (var i = 0; i < heads.length; i++) {
147 heads[i].drawContext(
148 ctx,
149 offsetX + heads[i].pos * cellWidth, offsetY,
150 cellWidth, cellHeight
151 );
152 }
153
154 this.drawContext(ctx, offsetX, offsetY, cellWidth, cellHeight);
155 };
156
15792 };