asciiflow2/js-lib/draw-select.js

148 lines
3.8 KiB
JavaScript

import * as c from './constants';
import Vector from './vector';
import State from './state';
import { MappedValue, Box } from './common';
import { DrawFunction, DrawErase } from './draw';
/**
* @implements {DrawFunction}
*/
export default class DrawSelect {
/**
* @param {State} state
*/
constructor(state) {
this.state = state;
/** @type {Vector} */
this.startPosition = null;
/** @type {Vector} */
this.endPosition = null;
/** @type {Vector} */
this.dragStart = null;
/** @type {Vector} */
this.dragEnd = null;
/** @type {boolean} */
this.finished = true;
/** @type {!Array<MappedValue>} */
this.selectedCells = [];
}
/** @inheritDoc */
start(position) {
// Must be dragging.
if (this.startPosition != null &&
this.endPosition != null &&
this.getSelectedBox().contains(position)) {
this.dragStart = position;
this.copyArea();
this.dragMove(position);
} else {
this.startPosition = position;
this.endPosition = null;
this.finished = false;
this.move(position);
}
}
getSelectedBox() {
return new Box(this.startPosition, this.endPosition);
}
copyArea() {
var nonEmptyCells = this.state.scratchCells.filter(function(value) {
var rawValue = value.cell.getRawValue();
return value.cell.getRawValue() != null && value.cell.getRawValue() != c.ERASE_CHAR;
});
var topLeft = this.getSelectedBox().topLeft();
this.selectedCells = nonEmptyCells.map(function(value) {
return new MappedValue(value.position.subtract(topLeft), value.cell.getRawValue());
});
}
/** @inheritDoc */
move(position) {
if (this.dragStart != null) {
this.dragMove(position);
return;
}
if (this.finished == true) {
return;
}
this.endPosition = position;
this.state.clearDraw();
var box = new Box(this.startPosition, position);
for (var i = box.startX; i <= box.endX; i++) {
for (var j = box.startY; j <= box.endY; j++) {
var current = new Vector(i, j);
// Effectively highlights the cell.
var currentValue = this.state.getCell(current).getRawValue();
this.state.drawValue(current,
currentValue == null ? c.ERASE_CHAR : currentValue);
}
}
}
dragMove(position) {
this.dragEnd = position;
this.state.clearDraw();
var eraser = new DrawErase(this.state);
eraser.start(this.startPosition);
eraser.move(this.endPosition);
var startPos = this.dragEnd.subtract(this.dragStart).add(this.getSelectedBox().topLeft());
this.drawSelected(startPos);
}
drawSelected(startPos) {
for (var { position, value } of this.selectedCells) {
this.state.drawValue(position.add(startPos), value);
}
}
/** @inheritDoc */
end() {
if (this.dragStart != null) {
this.state.commitDraw();
this.startPosition = null;
this.endPosition = null;
}
this.dragStart = null;
this.dragEnd = null;
this.finished = true;
}
/** @inheritDoc */
getCursor(position) {
if (this.startPosition != null &&
this.endPosition != null &&
new Box(this.startPosition, this.endPosition).contains(position)) {
return 'pointer';
}
return 'default';
}
/** @inheritDoc */
handleKey(value) {
if (this.startPosition != null &&
this.endPosition != null) {
if (value == c.KEY_COPY || value == c.KEY_CUT) {
this.copyArea();
}
if (value == c.KEY_CUT) {
var eraser = new DrawErase(this.state);
eraser.start(this.startPosition);
eraser.move(this.endPosition);
this.state.commitDraw();
}
}
if (value == c.KEY_PASTE) {
this.drawSelected(this.startPosition);
this.state.commitDraw();
}
}
}