src/app/core/application/selector.js
import { APP_STATE } from "../enums/app-state-enum";
import { stageManager as Stages } from "./stage-manager";
import { state as State } from "../application/state";
import { objects as Objects } from "../application/objects";
import { ELEMENTS_CLASS } from "../enums/elements-class-enum";
import { app as App } from "../../app";
import { COMPONENT_TYPE } from "../enums/component-type-enum";
export class Selector {
constructor() {
this._selectorPosStart;
this._selectorPosNow;
this._mode = "";
this._stage = Stages.getCurrentKonvaStage();
this._layer = Stages.getCurrentKonvaLayer();
this._selectorRect = new Konva.Rect({
x: 0,
y: 0,
width: 0,
height: 0,
stroke: "#33BCFF",
dash: [2, 2]
});
}
bootstrap() {
this.configureSelectorEvents();
this.addToLayer();
}
addToLayer() {
this._selectorRect.listening(false);
Stages.getCurrentKonvaLayer().add(this._selectorRect);
}
getSelectedAggregators() {
return Objects.getSelectedObjects();
}
getSelectedKonvaObjects() {
return this.getSelectedAggregators().map(function(aggregator) {
if (aggregator.konvaObject.children == undefined) {
return aggregator.konvaObject;
} else {
return aggregator.konvaObject.children.map(function(object) {
return object;
})[0];
}
});
}
getSelectedKonvaPoints() {
const objects = this.getSelectedKonvaObjects();
return objects.filter(
x => x.attrs.class != undefined && x.attrs.class == ELEMENTS_CLASS.POINT
);
}
getSelectedPoints() {
const objects = this.getSelectedAggregators().filter(
x =>
x.elementClass === ELEMENTS_CLASS.POINT ||
x.elementClass === ELEMENTS_CLASS.INTERSECTION_POINT
);
return objects.map(x => x.genericObject);
}
getSelectedPointsAggregators() {
const objects = this.getSelectedAggregators().filter(
x =>
x.elementClass === ELEMENTS_CLASS.POINT ||
x.elementClass === ELEMENTS_CLASS.INTERSECTION_POINT
);
return objects;
}
startDragSelector(posIn) {
this._selectorPosStart = { x: posIn.x, y: posIn.y };
this._selectorPosNow = { x: posIn.x, y: posIn.y };
}
updateDragSelector(posIn) {
if (State.getCurrentState() != APP_STATE.NONE) return;
App.clearSelectedTool();
const currentObjects = Objects.get();
const posRect = this.reverse(this._selectorPosStart, this._selectorPosNow);
this._selectorPosNow = { x: posIn.x, y: posIn.y };
this._selectorRect.x(posRect.x1);
this._selectorRect.y(posRect.y1);
this._selectorRect.width(posRect.x2 - posRect.x1);
this._selectorRect.height(posRect.y2 - posRect.y1);
this._selectorRect.visible(true);
for (let i = 0; i < currentObjects.length; i = i + 1) {
const aggregator = currentObjects[i];
const object = aggregator.konvaObject;
if (object == undefined) return;
if (object.children != undefined && object.children.length > 0) {
for (let j = 0; j < object.children.length; j++) {
this.style(object.children[j], this._selectorRect, aggregator);
}
} else {
this.style(object, this._selectorRect, aggregator);
}
}
this._stage.draw();
}
style(object, selectorRect, aggregator) {
if (object == undefined) return;
if (object.attrs.selectable != undefined) {
if (object.attrs.selectable == false) {
return;
}
}
if (this.hitCheck(object, selectorRect)) {
object.stroke("#33BCFF");
object.fill("#33BCFF");
this.setObject(aggregator);
} else {
if (object.attrs.style != undefined) {
this.removeObject(aggregator);
object.stroke(object.attrs.style.stroke);
object.fill(object.attrs.style.fill);
} else {
this.removeObject(aggregator);
object.stroke("grey");
}
}
}
hitCheck(shape1, shape2) {
let s1 = shape1.getClientRect();
let s2 = shape2.getClientRect();
let X = s1.x;
let Y = s1.y;
let A = s1.x + s1.width;
let B = s1.y + s1.height;
let X1 = s2.x;
let A1 = s2.x + s2.width;
let Y1 = s2.y;
let B1 = s2.y + s2.height;
if (A < X1 || A1 < X || B < Y1 || B1 < Y) {
return false;
} else {
return true;
}
}
setObject(object) {
Objects.setSelectedOject(object);
}
removeObject(object) {
Objects.removeSelectedOject(object);
}
reverse(r1, r2) {
let r1x = r1.x,
r1y = r1.y,
r2x = r2.x,
r2y = r2.y,
d;
if (r1x > r2x) {
d = Math.abs(r1x - r2x);
r1x = r2x;
r2x = r1x + d;
}
if (r1y > r2y) {
d = Math.abs(r1y - r2y);
r1y = r2y;
r2y = r1y + d;
}
return { x1: r1x, y1: r1y, x2: r2x, y2: r2y };
}
clear() {
Objects.get().forEach(aggregator => {
const object = aggregator.konvaObject;
if (object == undefined) return;
if (object.attrs.selectable != undefined) {
if (object.attrs.selectable == false) {
return;
}
}
if (object.children != undefined && object.children.length > 0) {
for (let j = 0; j < object.children.length; j++) {
this.clearAggregator(object.children[j], aggregator);
}
} else {
this.clearAggregator(object, aggregator);
}
});
}
clearAggregator(object, aggregator) {
if (object == undefined) return;
if (object.attrs.style != undefined) {
this.removeObject(aggregator);
object.stroke(object.attrs.style.stroke);
object.fill(object.attrs.style.fill);
} else {
this.removeObject(aggregator);
object.stroke("grey");
}
}
configureSelectorEvents() {
this._stage.on("mousedown touchstart", this.start.bind(this));
this._stage.on("mousemove touchmove", this.move.bind(this));
this._stage.on("mouseup touchend", this.end.bind(this));
}
start(event) {
const tool = App.getSelectedTool();
if (tool == undefined || tool.options.type != COMPONENT_TYPE.SELECTOR) {
return;
}
const pos = {
x: undefined,
y: undefined
};
if (event.evt.type === "touchstart") {
pos.x = event.target.pointerPos.x;
pos.y = event.target.pointerPos.y;
} else {
pos.x = event.evt.layerX;
pos.y = event.evt.layerY;
}
Stages.getCurrentKonvaLayer().add(this._selectorRect);
this._mode = "drawing";
this.startDragSelector(pos);
}
move(event) {
const tool = App.getSelectedTool();
if (tool == undefined || tool.options.type != COMPONENT_TYPE.SELECTOR) {
return;
}
const pos = {
x: undefined,
y: undefined
};
if (event.evt.type === "touchmove") {
pos.x = event.target.pointerPos.x;
pos.y = event.target.pointerPos.y;
} else {
pos.x = event.evt.layerX;
pos.y = event.evt.layerY;
}
if (this._mode === "drawing") {
this.updateDragSelector(pos);
}
}
end(event) {
this._selectorRect.remove();
this._mode = "";
this._selectorRect.visible(false);
this._stage.draw();
}
}
export const selector = new Selector();