{"version":3,"sources":["https://lively-kernel.org/lively4/BP2019RH1/src/internal/individuals-as-points/common/drawFreehand.js"],"names":["d3","ContextMenu","inside","FreehandSelection","ColorStore","deepCopy","boundDraw","boundSetPosition","boundOnDrawStop","FreehandDrawer","constructor","parentElement","canvas","svg","style","pos","x","y","transform","k","colorstore","_initializeContext","lastLinePoints","selections","listeners","_registerEventListeners","_draw","bind","_setPosition","_onDrawStop","start","addEventListener","capture","stop","removeEventListener","addListener","listener","push","drawSelections","leftPadding","paddingLeft","parseInt","topPadding","paddingTop","select","selectAll","filter","d","some","selection","color","remove","data","enter","append","attr","linePoints","map","join","applyScaling","factor","forEach","point","applyTransform","updateStyle","ctx","lineWidth","lineCap","strokeStyle","deleteSelections","_deleteSelection","newFreehandSelection","generateRandomHexColor","freehandSelectionCreated","e","position","_calculateRelativePosition","rect","target","getBoundingClientRect","clientX","left","clientY","top","lively","pt","buttons","shiftKey","save","translate","scale","beginPath","moveTo","lineTo","stroke","restore","_clear","clearRect","width","height","getContext","includes","splice","indexOf","freehandSelectionDeleted","evt","currentSelection","_findSelectionFromPosition","stopPropagation","preventDefault","selectionSVG","_getSVGElementFromSelection","_openSelectionMenu","result","linePointsArray","d3Selection","_groups","length","menuItems","freehandSelectionOnContextMenu","menu","openIn","document","body"],"mappings":"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","file":"drawFreehand.js","sourcesContent":["// needed to be able to call functions called with event listener with the context of FreehandDrawer and not the context of the element to which the event listener is bound\nvar boundDraw;\nvar boundSetPosition;\nvar boundOnDrawStop;\n\nimport d3 from 'src/external/d3.v5.js'\nimport ContextMenu from 'src/client/contextmenu.js'\n\n\nimport inside from \"https://lively-kernel.org/lively4/BP2019RH1/src/internal/individuals-as-points/common/npm-point-in-polygon.js\" //absolute path needed, don't ask why\n\nimport FreehandSelection from './freehandSelection.js'\nimport ColorStore from './color-store.js'\nimport { deepCopy } from './utils.js'\n\nexport default class FreehandDrawer {\n  constructor(parentElement, canvas, svg, style = {}) {\n    \n    // parentElement should be a div containing the canvas (on some level)\n    // canvas should lay on top of svg, canvas and svg should always have same extent\n    \n    this.parentElement = parentElement\n    this.canvas = canvas\n    this.svg = svg\n    \n    this.pos = { x: 0, y: 0 }\n    this.transform = {x: 0 , y: 0, k: 1}\n    this.colorstore = new ColorStore()\n    \n    this._initializeContext(canvas, style)\n  \n    this.lastLinePoints = []\n    this.selections = []\n\n    this.listeners = []\n\n    this._registerEventListeners()\n    boundDraw = this._draw.bind(this)\n    boundSetPosition = this._setPosition.bind(this)\n    boundOnDrawStop = this._onDrawStop.bind(this)\n  }\n\n  start() {\n    this.canvas.addEventListener('mousemove', boundDraw, {capture: true})\n    this.canvas.addEventListener('mousedown', boundSetPosition, {capture: true})\n    this.canvas.addEventListener('mouseup', boundOnDrawStop, {capture: true})\n  }\n\n  stop() {\n    this.canvas.removeEventListener('mousemove', boundDraw)\n    this.canvas.removeEventListener('mousedown', boundSetPosition)\n    this.canvas.removeEventListener('mouseup', boundOnDrawStop)\n  }\n \n  addListener(listener) {\n    this.listeners.push(listener)\n  }\n  \n  drawSelections() {\n    let leftPadding = this.canvas.style.paddingLeft ? parseInt(this.canvas.style.paddingLeft) : 0\n    let topPadding = this.canvas.style.paddingTop ? parseInt(this.canvas.style.paddingTop) : 0\n    \n    let selections = this.selections\n    d3.select(this.svg).selectAll(\"polygon\")\n      .filter(function (d){ return !selections.some(selection => selection.color === d.color)})\n      .remove()\n    \n    d3.select(this.svg).selectAll(\"polygon\")\n      .data(this.selections)\n      .enter()\n      .append(\"polygon\")\n      .attr(\"points\",function(d) { \n            return d.linePoints.map(function(d) {\n                return [d.x + leftPadding, d.y + topPadding].join(\",\");\n            }).join(\" \");\n          })\n      .style(\"fill\", function(d) {return d.color})\n      .style(\"fill-opacity\", \"0.3\")\n      .style(\"stroke\", \"black\")\n      .style(\"stroke-dasharray\", \"5,5\")\n  }\n  \n  applyScaling(factor) {\n    this.selections.forEach(selection => {\n      selection.linePoints = selection.linePoints.map(point => {\n        return {\"x\": point.x * factor.x, \"y\": point.y * factor.y}\n      })  \n    })\n    this.drawSelections()\n  }\n  \n  applyTransform(transform) {\n    this.transform = transform\n    d3.select(this.svg).selectAll(\"polygon\")\n      .attr(\"transform\", transform)\n  }\n  \n  updateStyle(style) {\n    this.ctx.lineWidth = style.lineWidth ? style.lineWidth : this.ctx.lineWidth\n    this.ctx.lineCap = style.lineCap ? style.lineCap : this.ctx.lineCap\n    this.ctx.strokeStyle = style.strokeStyle ? style.strokeStyle : this.ctx.strokeStyle\n  }\n  \n  deleteSelections() {\n    this.selections.forEach(selection => {\n      this._deleteSelection(selection)\n    })\n  }\n  \n  _onDrawStop() {\n    this.lastLinePoints.push({ \"x\": this.pos.x, \"y\": this.pos.y })\n    \n    let newFreehandSelection = new FreehandSelection(this.colorstore.generateRandomHexColor(), deepCopy(this.lastLinePoints))\n    this.selections.push(newFreehandSelection)\n\n    this.listeners.forEach(listener => {\n      listener.freehandSelectionCreated()\n    })\n    \n    this.lastLinePoints = []\n  }\n\n  _setPosition(e) {\n    let position = this._calculateRelativePosition(e) \n        \n    this.pos.x = position.x;\n    this.pos.y = position.y;\n  }\n  \n  _calculateRelativePosition(e) {\n    var rect = e.target.getBoundingClientRect()\n    let paddingLeft = this.canvas.style.paddingLeft ? parseInt(this.canvas.style.paddingLeft) : 0\n    let paddingTop = this.canvas.style.paddingTop ? parseInt(this.canvas.style.paddingTop) : 0\n    var x = e.clientX - rect.left - paddingLeft\n    var y = e.clientY - rect.top - paddingTop\n    \n    // apply tranformation\n    x = (x - this.transform.x) / this.transform.k\n    y = (y - this.transform.y) / this.transform.k\n    \n    return lively.pt(x,y)\n  }\n  \n\n  _draw(e) {\n    // mouse left button and shiftKey must be pressed\n    if (e.buttons !== 1) return\n    if (!e.shiftKey) return\n    \n    this.ctx.save()\n    this.ctx.translate(this.transform.x, this.transform.y)\n    this.ctx.scale(this.transform.k, this.transform.k)\n    \n    this.ctx.beginPath() // begin\n\n    this.ctx.moveTo(this.pos.x, this.pos.y) // from\n\n    this.lastLinePoints.push({ \"x\": this.pos.x, \"y\": this.pos.y })\n\n    this._setPosition(e)\n    this.ctx.lineTo(this.pos.x, this.pos.y) // to\n\n    this.ctx.stroke() // draw it!\n    this.ctx.restore()\n  }\n\n  _clear() {\n    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)\n  }\n  \n  _initializeContext(canvas, style) {\n    this.ctx = canvas.getContext('2d')\n    this.ctx.lineWidth = style.lineWidth ? style.lineWidth : 1\n    this.ctx.lineCap = style.lineCap ? style.lineCap : 'round'\n    this.ctx.strokeStyle = style.strokeStyle ? style.strokeStyle : \"#000000\"\n  }\n  \n  _deleteSelection(selection) {\n    if (this.selections.includes(selection) ) {\n      this.selections.splice(this.selections.indexOf(selection), 1)\n    }\n    this.listeners.forEach(listener => listener.freehandSelectionDeleted(selection))\n  }\n  \n  _registerEventListeners() {\n    this.canvas.addEventListener(\"contextmenu\", (evt) => {\n      let currentSelection = this._findSelectionFromPosition(evt)\n      if (currentSelection) {\n        evt.stopPropagation()\n        evt.preventDefault()\n        let selectionSVG = this._getSVGElementFromSelection(currentSelection)\n        this._openSelectionMenu(evt, currentSelection, selectionSVG)\n      }\n    })\n  }\n  \n  _findSelectionFromPosition(evt) {\n    let result = false\n    let position = this._calculateRelativePosition(evt)\n    this.selections.forEach(selection => {\n      let linePointsArray = selection.linePoints.map(point => [point.x, point.y])\n      if (inside([position.x, position.y], linePointsArray)) {\n        result = selection\n      } \n    })\n    return result\n  }\n  \n  _getSVGElementFromSelection(selection) {\n    var d3Selection = d3.select(this.svg).selectAll(\"polygon\").filter(function(svg) {\n      return svg.color === selection.color;\n    })\n    \n    // happily assuming that we always have just one corresponding selectionElement \n    // (which given the usage of color as a kinda identifier should be fine)\n    if (d3Selection._groups.length >= 1) return d3Selection._groups[0][0] \n  }\n  \n  async _openSelectionMenu(evt, selection, selectionSVG) {\n    const menuItems = [\n      ['Create new visualization from selection', () => {\n        this.listeners.forEach(listener => listener.freehandSelectionOnContextMenu(evt, selection, selectionSVG))\n      }],\n      ['Delete selection', () => this._deleteSelection(selection)]\n    ]\n    const menu = await ContextMenu.openIn(document.body, evt, this.canvas, document.body,  menuItems)\n  }\n}"]}