Added snap to nearest special char for mobile, mobile detection logic, refactoring of standard directions into constants.

This commit is contained in:
Lewis Hemens 2014-02-20 00:10:20 +00:00
parent 8b5e3139a6
commit 92e413357a
4 changed files with 80 additions and 30 deletions

View File

@ -5,7 +5,6 @@ java -client -jar closure-compiler.jar \
--js js-lib/controller.js \ --js js-lib/controller.js \
--js js-lib/state.js \ --js js-lib/state.js \
--js js-lib/launch.js \ --js js-lib/launch.js \
--warning_level=VERBOSE --formatting=PRETTY_PRINT --language_in=ECMASCRIPT5 --compilation_level=WHITESPACE_ONLY \ --warning_level=VERBOSE --formatting=PRETTY_PRINT --language_in=ECMASCRIPT5 --compilation_level=ADVANCED_OPTIMIZATIONS \
--externs=jquery-1.9-externs.js \ --externs=jquery-1.9-externs.js \
> js-compiled.js \ > js-compiled.js
&& cp js-compiled.js js-compiled.js~

View File

@ -5,8 +5,9 @@
// Define namespace for closure compiler but don't make it a requirement. // Define namespace for closure compiler but don't make it a requirement.
try { try {
goog.provide('ascii'); goog.provide('ascii');
throw 1;
} catch (e) { } catch (e) {
window.ascii = {}; window.ascii = window.ascii || {};
} }
/** @const */ var MAX_GRID_WIDTH = 2000; /** @const */ var MAX_GRID_WIDTH = 2000;
@ -39,6 +40,11 @@ try {
/** @const */ var KEY_LEFT = '<left>'; /** @const */ var KEY_LEFT = '<left>';
/** @const */ var KEY_RIGHT = '<right>'; /** @const */ var KEY_RIGHT = '<right>';
// http://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript
/** @const */ var TOUCH_ENABLED =
'ontouchstart' in window ||
'onmsgesturechange' in window;
/** /**
* Stores a 2D vector. * Stores a 2D vector.
* *
@ -95,6 +101,13 @@ ascii.Vector.prototype.scale = function(scale) {
return new ascii.Vector(this.x * scale, this.y * scale); return new ascii.Vector(this.x * scale, this.y * scale);
}; };
/** @const */ var DIR_LEFT = new ascii.Vector(-1, 0);
/** @const */ var DIR_RIGHT = new ascii.Vector(1, 0);
/** @const */ var DIR_UP = new ascii.Vector(0, -1);
/** @const */ var DIR_DOWN = new ascii.Vector(0, 1);
/** @const */ var DIRECTIONS = [ DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN ];
/** /**
* An individual cell within the diagram and it's current value. * An individual cell within the diagram and it's current value.
* *

View File

@ -182,18 +182,18 @@ ascii.DrawText.prototype.handleKey = function(value) {
if (this.currentPosition == null) { if (this.currentPosition == null) {
return; return;
} }
var nextPosition = this.currentPosition.add(new ascii.Vector(1, 0)); var nextPosition = this.currentPosition.add(DIR_RIGHT);
if (value == KEY_RETURN || this.state.getCell(nextPosition).isSpecial()) { if (value == KEY_RETURN || this.state.getCell(nextPosition).isSpecial()) {
// Pressed return key or hit box, so clear this cell and new line. // Pressed return key or hit box, so clear this cell and new line.
this.state.clearDraw(); this.state.clearDraw();
nextPosition = this.startPosition.add(new ascii.Vector(0, 1)); nextPosition = this.startPosition.add(DIR_DOWN);
this.startPosition = nextPosition; this.startPosition = nextPosition;
} }
if (value == KEY_BACKSPACE && this.startPosition.x <= nextPosition.x) { if (value == KEY_BACKSPACE && this.startPosition.x <= nextPosition.x) {
// Pressed backspace key, so clear this cell and go back. // Pressed backspace key, so clear this cell and go back.
this.state.clearDraw(); this.state.clearDraw();
nextPosition = this.currentPosition.add(new ascii.Vector(-1, 0)); nextPosition = this.currentPosition.add(DIR_LEFT);
if (nextPosition.x < this.startPosition.x) { if (nextPosition.x < this.startPosition.x) {
nextPosition.x = this.startPosition.x; nextPosition.x = this.startPosition.x;
} }
@ -202,19 +202,19 @@ ascii.DrawText.prototype.handleKey = function(value) {
} }
if (value == KEY_UP) { if (value == KEY_UP) {
this.state.clearDraw(); this.state.clearDraw();
this.startPosition = nextPosition = this.currentPosition.add(new ascii.Vector(0, -1)) this.startPosition = nextPosition = this.currentPosition.add(DIR_UP);
} }
if (value == KEY_LEFT) { if (value == KEY_LEFT) {
this.state.clearDraw(); this.state.clearDraw();
this.startPosition = nextPosition = this.currentPosition.add(new ascii.Vector(-1, 0)) this.startPosition = nextPosition = this.currentPosition.add(DIR_LEFT);
} }
if (value == KEY_RIGHT) { if (value == KEY_RIGHT) {
this.state.clearDraw(); this.state.clearDraw();
this.startPosition = nextPosition = this.currentPosition.add(new ascii.Vector(1, 0)) this.startPosition = nextPosition = this.currentPosition.add(DIR_RIGHT);
} }
if (value == KEY_DOWN) { if (value == KEY_DOWN) {
this.state.clearDraw(); this.state.clearDraw();
this.startPosition = nextPosition = this.currentPosition.add(new ascii.Vector(0, 1)) this.startPosition = nextPosition = this.currentPosition.add(DIR_DOWN);
} }
if (value.length == 1) { if (value.length == 1) {
@ -279,22 +279,25 @@ ascii.DrawMove = function(state) {
}; };
ascii.DrawMove.prototype.start = function(position) { ascii.DrawMove.prototype.start = function(position) {
this.startPosition = position; this.startPosition = TOUCH_ENABLED
var context = this.state.getContext(position); ? this.snapToNearest(position)
var directions = [ : position;
new ascii.Vector(1, 0), this.ends = null;
new ascii.Vector(-1, 0),
new ascii.Vector(0, 1), // If this isn't a special cell then quit, or things get weird.
new ascii.Vector(0, -1)]; if (!this.state.getCell(this.startPosition).isSpecial()) {
return;
}
var context = this.state.getContext(this.startPosition);
var ends = []; var ends = [];
for (var i in directions) { for (var i in DIRECTIONS) {
var midPoints = this.followLine(position, directions[i]); var midPoints = this.followLine(this.startPosition, DIRECTIONS[i]);
for (var k in midPoints) { for (var k in midPoints) {
var midPoint = midPoints[k]; var midPoint = midPoints[k];
// Clockwise is a lie, it is true if we move vertically first. // Clockwise is a lie, it is true if we move vertically first.
var clockwise = (directions[i].x != 0); var clockwise = (DIRECTIONS[i].x != 0);
var midPointContext = this.state.getContext(midPoint); var midPointContext = this.state.getContext(midPoint);
// Special case, a straight line with no turns. // Special case, a straight line with no turns.
@ -303,13 +306,13 @@ ascii.DrawMove.prototype.start = function(position) {
continue; continue;
} }
// Continue following lines from the midpoint. // Continue following lines from the midpoint.
for (var j in directions) { for (var j in DIRECTIONS) {
if (directions[i].add(directions[j]).length() == 0 || if (DIRECTIONS[i].add(DIRECTIONS[j]).length() == 0 ||
directions[i].add(directions[j]).length() == 2) { DIRECTIONS[i].add(DIRECTIONS[j]).length() == 2) {
// Don't go back on ourselves, or don't carry on in same direction. // Don't go back on ourselves, or don't carry on in same direction.
continue; continue;
} }
var secondEnds = this.followLine(midPoint, directions[j]); var secondEnds = this.followLine(midPoint, DIRECTIONS[j]);
// Ignore any directions that didn't go anywhere. // Ignore any directions that didn't go anywhere.
if (secondEnds.length == 0) { if (secondEnds.length == 0) {
continue; continue;
@ -321,7 +324,7 @@ ascii.DrawMove.prototype.start = function(position) {
} }
this.ends = ends; this.ends = ends;
// Redraw the new lines after we have cleared the existing ones. // Redraw the new lines after we have cleared the existing ones.
this.move(position); this.move(this.startPosition);
}; };
ascii.DrawMove.prototype.move = function(position) { ascii.DrawMove.prototype.move = function(position) {
@ -368,6 +371,41 @@ ascii.DrawMove.prototype.followLine = function(startPosition, direction) {
} }
}; };
/**
* For a given position, finds the nearest cell that is of any interest to the
* move tool, e.g. a corner or a line. Will look up to 1 cell in each direction
* including diagonally.
* @return {ascii.Vector}
*/
ascii.DrawMove.prototype.snapToNearest = function(position) {
if (this.state.getCell(position).isSpecial()) {
return position;
}
var allDirections = DIRECTIONS.concat([
DIR_LEFT.add(DIR_UP),
DIR_LEFT.add(DIR_DOWN),
DIR_RIGHT.add(DIR_UP),
DIR_RIGHT.add(DIR_DOWN)]);
var bestDirection = null;
var bestContextSum = 0;
for (var i in allDirections) {
// Find the most connected cell, essentially.
var newPos = position.add(allDirections[i]);
var contextSum = this.state.getContext(newPos).sum();
if (this.state.getCell(newPos).isSpecial()
&& contextSum > bestContextSum) {
bestDirection = allDirections[i];
bestContextSum = contextSum;
}
}
if (bestDirection == null) {
// Didn't find anything, so just return the current cell.
return position;
}
return position.add(bestDirection);
}
ascii.DrawMove.prototype.getCursor = function(position) { ascii.DrawMove.prototype.getCursor = function(position) {
if (this.state.getCell(position).isSpecial()) { if (this.state.getCell(position).isSpecial()) {
return 'pointer'; return 'pointer';

View File

@ -125,10 +125,10 @@ ascii.State.prototype.getDrawValue = function(position) {
* @return {ascii.CellContext} * @return {ascii.CellContext}
*/ */
ascii.State.prototype.getContext = function(position) { ascii.State.prototype.getContext = function(position) {
var left = this.getCell(position.add(new ascii.Vector(-1, 0))).isSpecial(); var left = this.getCell(position.add(DIR_LEFT)).isSpecial();
var right = this.getCell(position.add(new ascii.Vector(1, 0))).isSpecial(); var right = this.getCell(position.add(DIR_RIGHT)).isSpecial();
var up = this.getCell(position.add(new ascii.Vector(0, -1))).isSpecial(); var up = this.getCell(position.add(DIR_UP)).isSpecial();
var down = this.getCell(position.add(new ascii.Vector(0, 1))).isSpecial(); var down = this.getCell(position.add(DIR_DOWN)).isSpecial();
return new ascii.CellContext(left, right, up, down); return new ascii.CellContext(left, right, up, down);
}; };