197 lines
5.7 KiB
JavaScript
197 lines
5.7 KiB
JavaScript
goog.provide('ascii.StateController');
|
|
|
|
goog.require('ascii.Vector');
|
|
|
|
/**
|
|
* Common interface for different drawing functions, e.g. box, line, etc.
|
|
* @interface
|
|
*/
|
|
function DrawFunction() {}
|
|
/** Start of drawing. @param {ascii.Vector} position */
|
|
DrawFunction.prototype.start = function(position) {};
|
|
/** Drawing move. @param {ascii.Vector} position */
|
|
DrawFunction.prototype.move = function(position) {};
|
|
/** End of drawing. @param {ascii.Vector} position */
|
|
DrawFunction.prototype.end = function(position) {};
|
|
|
|
/**
|
|
* @constructor
|
|
* @implements {DrawFunction}
|
|
* @param {ascii.State} state
|
|
*/
|
|
function DrawBox(state) {
|
|
this.state = state;
|
|
/** @type {ascii.Vector} */ this.startPosition = null;
|
|
/** @type {ascii.Vector} */ this.endPosition = null;
|
|
}
|
|
|
|
DrawBox.prototype.start = function(position) {
|
|
this.startPosition = position;
|
|
this.endPosition = position;
|
|
this.draw();
|
|
};
|
|
DrawBox.prototype.move = function(position) {
|
|
this.endPosition = position;
|
|
this.state.clearDraw();
|
|
this.draw();
|
|
};
|
|
DrawBox.prototype.end = function(position) {
|
|
this.state.commitDraw();
|
|
};
|
|
|
|
/** Draws the currently dragged out box. */
|
|
DrawBox.prototype.draw = function() {
|
|
var x1 = Math.min(this.startPosition.x, this.endPosition.x);
|
|
var y1 = Math.min(this.startPosition.y, this.endPosition.y);
|
|
var x2 = Math.max(this.startPosition.x, this.endPosition.x);
|
|
var y2 = Math.max(this.startPosition.y, this.endPosition.y);
|
|
|
|
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.drawSpecial(new ascii.Vector(x, y1));
|
|
this.state.drawSpecial(new ascii.Vector(x, y2));
|
|
}
|
|
for (var y = y1 + 1; y < y2; y++) {
|
|
this.state.drawSpecial(new ascii.Vector(x1, y));
|
|
this.state.drawSpecial(new ascii.Vector(x2, y));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @constructor
|
|
* @implements {DrawFunction}
|
|
* @param {ascii.State} state
|
|
*/
|
|
function DrawLine(state) {
|
|
this.state = state;
|
|
/** @type {ascii.Vector} */ this.startPosition = null;
|
|
/** @type {ascii.Vector} */ this.endPosition = null;
|
|
}
|
|
|
|
DrawLine.prototype.start = function(position) {
|
|
this.startPosition = position;
|
|
this.endPosition = position;
|
|
this.draw();
|
|
};
|
|
DrawLine.prototype.move = function(position) {
|
|
this.endPosition = position;
|
|
this.state.clearDraw();
|
|
this.draw();
|
|
};
|
|
DrawLine.prototype.end = function(position) {
|
|
this.state.commitDraw();
|
|
};
|
|
|
|
/**
|
|
* Draws the currently dragged out line.
|
|
*/
|
|
DrawLine.prototype.draw = function() {
|
|
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);
|
|
var hX2 = Math.max(this.startPosition.x, this.endPosition.x);
|
|
var vY2 = Math.max(this.startPosition.y, this.endPosition.y);
|
|
|
|
var hY = isClockwise ? this.startPosition.y : this.endPosition.y;
|
|
var vX = isClockwise ? this.endPosition.x : this.startPosition.x;
|
|
|
|
while (hX1++ < hX2) {
|
|
this.state.drawSpecial(new ascii.Vector(hX1, hY));
|
|
}
|
|
while (vY1++ < vY2) {
|
|
this.state.drawSpecial(new ascii.Vector(vX, vY1));
|
|
}
|
|
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, value) {
|
|
this.state = state;
|
|
this.value = value;
|
|
}
|
|
|
|
DrawFreeform.prototype.start = function(position) {
|
|
this.state.setValue(position, this.value);
|
|
};
|
|
DrawFreeform.prototype.move = function(position) {
|
|
this.state.setValue(position, this.value);
|
|
};
|
|
|
|
DrawFreeform.prototype.end = function(position) {
|
|
};
|
|
|
|
/**
|
|
* Handles management of the diagram state. Input events are cleaned in the
|
|
* parent controller and passed down to this class for dealing with drawing.
|
|
*
|
|
* @constructor
|
|
* @param {ascii.State} state
|
|
*/
|
|
ascii.StateController = function(state) {
|
|
/** @type {ascii.State} */ this.state = state;
|
|
/** @type {DrawFunction} */ this.drawFunction = new DrawBox(state);
|
|
|
|
$('#box-button').click(function(e) {
|
|
this.drawFunction = new DrawBox(state);
|
|
}.bind(this));
|
|
|
|
$('#line-button').click(function(e) {
|
|
this.drawFunction = new DrawLine(state);
|
|
}.bind(this));
|
|
|
|
$('#freeform-button').click(function(e) {
|
|
this.drawFunction = new DrawFreeform(state, 'O');
|
|
}.bind(this));
|
|
|
|
$('#erase-button').click(function(e) {
|
|
this.drawFunction = new DrawFreeform(state, null);
|
|
}.bind(this));
|
|
};
|
|
|
|
/**
|
|
* Handles a press in the context of the drawing frame.
|
|
* @param {ascii.Vector} position
|
|
*/
|
|
ascii.StateController.prototype.handleDrawingPress = function(position) {
|
|
this.drawFunction.start(position);
|
|
};
|
|
|
|
/**
|
|
* Handles a release in the context of the drawing frame.
|
|
* @param {ascii.Vector} position
|
|
*/
|
|
ascii.StateController.prototype.handleDrawingRelease = function(position) {
|
|
this.drawFunction.end(position);
|
|
};
|
|
|
|
/**
|
|
* Handles a move in the context of the drawing frame.
|
|
* @param {ascii.Vector} position
|
|
*/
|
|
ascii.StateController.prototype.handleDrawingMove = function(position) {
|
|
this.drawFunction.move(position);
|
|
};
|