Home Reference Source Repository

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();