New state model is magical, introduced special character whose value is 'inferred' from it's surroundings. This may be the coolest thing ever.

This commit is contained in:
Lewis Hemens 2014-01-13 23:17:02 +00:00
parent 7d508e2ede
commit e0b0505332
4 changed files with 99 additions and 26 deletions

View File

@ -46,19 +46,19 @@ DrawBox.prototype.draw = function() {
var x2 = Math.max(this.startPosition.x, this.endPosition.x);
var y2 = Math.max(this.startPosition.y, this.endPosition.y);
this.state.drawValue(new ascii.Vector(x1, y1), '+');
this.state.drawValue(new ascii.Vector(x1, y2), '+');
this.state.drawValue(new ascii.Vector(x2, y1), '+');
this.state.drawValue(new ascii.Vector(x2, y2), '+');
this.state.drawSpecial(new ascii.Vector(x1, y1));
this.state.drawSpecial(new ascii.Vector(x1, y2));
this.state.drawSpecial(new ascii.Vector(x2, y1));
this.state.drawSpecial(new ascii.Vector(x2, y2));
for (var x = x1 + 1; x < x2; x++) {
this.state.drawValue(new ascii.Vector(x, y1), '\u2014');
this.state.drawValue(new ascii.Vector(x, y2), '\u2014');
this.state.drawSpecial(new ascii.Vector(x, y1));
this.state.drawSpecial(new ascii.Vector(x, y2));
}
for (var y = y1 + 1; y < y2; y++) {
this.state.drawValue(new ascii.Vector(x1, y), '|');
this.state.drawValue(new ascii.Vector(x2, y), '|');
this.state.drawSpecial(new ascii.Vector(x1, y));
this.state.drawSpecial(new ascii.Vector(x2, y));
}
};
@ -87,10 +87,21 @@ DrawLine.prototype.end = function(position) {
this.state.commitDraw();
};
/** Draws the currently dragged out line. */
/**
* Draws the currently dragged out line.
*/
DrawLine.prototype.draw = function() {
// TODO: Infer line direction.
var isClockwise = true;
var upStart = this.state.isSpecial(
this.startPosition.add(new ascii.Vector(0, -1)));
var downStart = this.state.isSpecial(
this.startPosition.add(new ascii.Vector(0, 1)));
var leftEnd = this.state.isSpecial(
this.endPosition.add(new ascii.Vector(-1, 0)));
var rightEnd = this.state.isSpecial(
this.endPosition.add(new ascii.Vector(1, 0)));
// Look at the start and end contexts to infer line orientation.
var isClockwise = (upStart && downStart) || (leftEnd && rightEnd);
var hX1 = Math.min(this.startPosition.x, this.endPosition.x);
var vY1 = Math.min(this.startPosition.y, this.endPosition.y);
@ -101,34 +112,35 @@ DrawLine.prototype.draw = function() {
var vX = isClockwise ? this.endPosition.x : this.startPosition.x;
while (hX1++ < hX2) {
this.state.drawValue(new ascii.Vector(hX1, hY), '\u2014');
this.state.drawSpecial(new ascii.Vector(hX1, hY));
}
while (vY1++ < vY2) {
this.state.drawValue(new ascii.Vector(vX, vY1), '|');
this.state.drawSpecial(new ascii.Vector(vX, vY1));
}
this.state.drawValue(new ascii.Vector(this.startPosition.x, this.startPosition.y), '+');
this.state.drawValue(new ascii.Vector(this.endPosition.x, this.endPosition.y), '+');
this.state.drawValue(new ascii.Vector(vX, hY), '+');
this.state.drawSpecial(new ascii.Vector(this.startPosition.x, this.startPosition.y));
this.state.drawSpecial(new ascii.Vector(this.endPosition.x, this.endPosition.y));
this.state.drawSpecial(new ascii.Vector(vX, hY));
};
/**
* @constructor
* @implements {DrawFunction}
* @param {ascii.State} state
* @param {?string} value
*/
function DrawFreeform(state) {
function DrawFreeform(state, value) {
this.state = state;
this.value = value;
}
DrawFreeform.prototype.start = function(position) {
this.state.drawValue(position, 'O');
this.state.setValue(position, this.value);
};
DrawFreeform.prototype.move = function(position) {
this.state.drawValue(position, 'O');
this.state.setValue(position, this.value);
};
DrawFreeform.prototype.end = function(position) {
this.state.commitDraw();
};
/**
@ -151,7 +163,11 @@ ascii.StateController = function(state) {
}.bind(this));
$('#freeform-button').click(function(e) {
this.drawFunction = new DrawFreeform(state);
this.drawFunction = new DrawFreeform(state, 'O');
}.bind(this));
$('#erase-button').click(function(e) {
this.drawFunction = new DrawFreeform(state, null);
}.bind(this));
};

View File

@ -1,6 +1,10 @@
goog.provide('ascii.State');
/** @const */ var MAX_GRID_SIZE = 1000;
/** @const */ var SPECIAL_VALUE = '+';
/** @const */ var SPECIAL_LINE_H = '\u2014';
/** @const */ var SPECIAL_LINE_V = '|';
/**
* An individual cell within the diagram and it's current value.
@ -51,17 +55,17 @@ ascii.State.prototype.getCell = function(vector) {
* be used directly in many cases. Used drawValue instead.
*
* @param {ascii.Vector} position
* @param {string} value
* @param {?string} value
*/
ascii.State.prototype.setValue = function(position, value) {
this.getCell(position).value = value;
};
/**
* Sets the cells scratch (uncommitted) value at the given position.
*
* @param {ascii.Vector} position
* @param {string} value
* @param {?string} value
*/
ascii.State.prototype.drawValue = function(position, value) {
var cell = this.getCell(position);
@ -69,6 +73,15 @@ ascii.State.prototype.drawValue = function(position, value) {
cell.scratchValue = value;
};
/**
* Sets the cells scratch value to be the special value.
*
* @param {ascii.Vector} position
*/
ascii.State.prototype.drawSpecial = function(position) {
this.drawValue(position, SPECIAL_VALUE);
};
/**
* Clears the current drawing scratchpad.
*/
@ -79,6 +92,49 @@ ascii.State.prototype.clearDraw = function() {
this.scratchCells.length = 0;
};
/**
* Returns true if the cell at the given position is special.
*
* @param {ascii.Vector} position
* @return {boolean}
*/
ascii.State.prototype.isSpecial = function(position) {
var cell = this.getCell(position);
var value = cell.scratchValue != null ? cell.scratchValue : cell.value;
return value == SPECIAL_VALUE;
};
/**
* Returns the draw value of a cell at the given position.
*
* @param {ascii.Vector} position
* @return {?string}
*/
ascii.State.prototype.getDrawValue = function(position) {
var cell = this.getCell(position);
var value = cell.scratchValue != null ? cell.scratchValue : cell.value;
if (value != SPECIAL_VALUE) {
return value;
}
// Magic time.
var left = this.isSpecial(position.add(new ascii.Vector(-1, 0)));
var right = this.isSpecial(position.add(new ascii.Vector(1, 0)));
var up = this.isSpecial(position.add(new ascii.Vector(0, -1)));
var down = this.isSpecial(position.add(new ascii.Vector(0, 1)));
if (left && right && !up && !down) {
return SPECIAL_LINE_H;
}
if (!left && !right && up && down) {
return SPECIAL_LINE_V;
}
if (left && right && up && down) {
return SPECIAL_LINE_H;
}
return SPECIAL_VALUE;
};
/**
* Ends the current draw, commiting anything currently drawn the scratchpad.
*/

View File

@ -96,7 +96,7 @@ ascii.View.prototype.render = function() {
this.context.font = '15px Courier New';
for (var i = startOffset.x; i < endOffset.x; i++) {
for (var j = startOffset.y; j < endOffset.y; j++) {
var cellValue = this.state.cells[i][j].getDrawValue();
var cellValue = this.state.getDrawValue(new ascii.Vector(i, j));
if (cellValue != null) {
context.fillText(cellValue,
i * CHARACTER_PIXELS - this.offset.x + 3,

View File

@ -13,7 +13,7 @@
left: 0px;
right: 0px;
z-index: 100;
width: 300px;
width: 400px;
background: #EEE;
text-align: center;
}
@ -38,6 +38,7 @@ button {
<button id="box-button">Box</button>
<button id="line-button">Line</button>
<button id="freeform-button">Freeform</button>
<button id="erase-button">Erase</button>
</div>
<canvas id="ascii-canvas"></canvas>
<script src="jquery-1.9.1.min.js"></script>