{"version":3,"sources":["https://lively-kernel.org/lively4/lively4-tom/src/components/tools/lively-image-editor.js"],"names":["Morph","LivelyImageEditor","initialize","windowTitle","canvas","get","height","width","ctx","getContext","value","color","penSize","lively","html","registerKeys","removeEventListener","addEventListener","e","onPointerDown","onPointerMove","onPointerUp","evt","shiftKey","onContextMenu","stopPropagation","preventDefault","onPenColor","detail","onPenSize","target","loadFromImageElement","url","getAttribute","loadImage","setAttribute","onKeyDown","key","String","fromCharCode","keyCode","ctrlKey","onSave","saveFile","data","toDataURL","lastSource","files","copyURLtoURL","getURL","setURL","currentEditor","getValue","size","toString","match","resolvedURL","swxURL","img","Image","onload","src","drawImage","posFromEvent","getPosition","subPt","getGlobalPosition","setTarget","paint","pos","strokeStyle","lineWidth","lastPos","moveTo","x","y","lineTo","closePath","stroke","isDown","beginPath","undefined","updateChangeIndicator","saveToTarget","notify","onSaveAs","prompt","onOpen","menuElements","menu","contextmenu","openIn","document","body","livelyMigrate","other","_lastSource","newSource","style","backgroundColor","textChanged","livelyExample"],"mappings":"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","file":"lively-image-editor.js","sourcesContent":["import Morph from 'src/components/widgets/lively-morph.js';\n\nexport default class LivelyImageEditor extends Morph {\n  async initialize() {\n    this.windowTitle = \"Image Editor\";\n\n    this.canvas = this.get(\"#canvas\")\n    this.canvas.height = 500\n    this.canvas.width = 500\n\n    this.ctx = this.canvas.getContext(\"2d\");\n\n    this.get(\"#penColor\").value = this.color;\n    this.get(\"#penSize\").value = this.penSize;\n\n    lively.html.registerKeys(this, \"keys\", this, true)\n    \n    lively.removeEventListener(\"pointer\", this)\n    lively.addEventListener(\"pointer\", this, \"pointerdown\", e => this.onPointerDown(e))\n    lively.addEventListener(\"pointer\", this, \"pointermove\", e => this.onPointerMove(e))\n    lively.addEventListener(\"pointer\", this, \"pointerup\", e => this.onPointerUp(e))\n\n    lively.addEventListener('pointer', this, \"contextmenu\", evt => {\n      if (!evt.shiftKey) {\n        this.onContextMenu(evt)\n        evt.stopPropagation();\n        evt.preventDefault();\n        return true;\n      }\n    }, false);\n    \n    \n    lively.addEventListener(\"imageeditor\", this.get('#penColor'), \"value-changed\", \n      e => this.onPenColor(e.detail.value));  \n    lively.addEventListener(\"imageeditor\", this.get('#penSize'), \"value-changed\", \n      e => this.onPenSize(e.detail.value)); \n    \n    if(this.target) {\n      this.loadFromImageElement(this.target)\n    } else {\n      var url = this.getAttribute(\"src\")\n      if (url) {\n        this.loadImage(url)\n      }   \n    }\n  }\n  \n  // ACCESSORS\n  \n  get color() {\n    return this.getAttribute(\"color\")\n  }\n  \n  set color(value) {\n    this.setAttribute(\"color\", value)\n  }\n  \n  get penSize() {\n    return this.getAttribute(\"pen-size\")\n  }\n  \n  set penSize(value) {\n    this.setAttribute(\"pen-size\", value)\n  }\n  \n  onKeyDown(evt) {\n    var key = String.fromCharCode(evt.keyCode)\n    if (evt.ctrlKey && key == \"S\") {\n      this.onSave()  \n    }\n  }\n\n  \n  // BEGIN EDITOR API\n  saveFile() {\n    \n    var data = this.canvas.toDataURL()\n    this.lastSource = data\n    return lively.files.copyURLtoURL(data, this.getURL())\n  }\n\n  getURL(url) {\n    return this.getAttribute(\"src\")\n  }\n\n  setURL(url) {\n    if(this.getURL() != url) {\n      this.loadImage(url)\n    }\n  }\n  \n  currentEditor() {\n    var canvas = this.canvas\n    return {\n      getValue() { return canvas.toDataURL()}\n    }\n  }\n  // END EDITOR API\n  \n  \n  onPenColor(color) {\n    this.color = color\n  }\n  \n  onPenSize(size) {\n    this.penSize = size\n  }\n  \n  \n  \n  loadImage(url) {\n      \n    this.setAttribute(\"src\", url)\n      \n    if (!url.toString().match(/^https?:\\/\\//)) {\n      var resolvedURL = lively.swxURL(url)\n    } else {\n      resolvedURL = url\n    }\n      \n    \n    var img = new Image();\n    img.onload = () => {\n      this.loadFromImageElement(img) \n    };\n    img.src = resolvedURL\n  }\n  \n  loadFromImageElement(img) {\n    this.canvas.height = img.height\n    this.canvas.width = img.width\n    this.ctx.drawImage(img, 0, 0); // Or at whatever offset you like\n    this.lastSource = this.canvas.toDataURL();\n\n  }\n  \n  posFromEvent(evt) {\n    return lively.getPosition(evt).subPt(lively.getGlobalPosition(this.canvas))\n  }\n  \n  setTarget(img) {\n    this.target = img\n    this.loadFromImageElement(img)\n  }\n  \n  paint(pos) {\n    this.ctx.strokeStyle =  this.color;\n    this.ctx.lineWidth = this.penSize;\n    if (this.lastPos) {\n      this.ctx.moveTo(this.lastPos.x, this.lastPos.y);      \n      this.ctx.lineTo(pos.x, pos.y);\n     \n     this.ctx.closePath();\n      this.ctx.stroke();\n    }\n    this.lastPos = pos\n  }\n\n  onPointerDown(evt) {\n    this.isDown = true\n    var pos = this.posFromEvent(evt)\n    this.ctx.beginPath()\n    this.paint(pos)\n  }\n  \n  onPointerMove(evt) {\n    if (this.isDown) {\n      var pos = this.posFromEvent(evt)\n      this.paint(pos)\n    }\n  }\n\n  onPointerUp(evt) {\n    var pos = this.posFromEvent(evt)\n    this.paint(pos)\n    this.isDown = false\n    this.lastPos = undefined\n    this.updateChangeIndicator()\n  }\n  \n  saveToTarget() {\n    var data = this.canvas.toDataURL()\n    this.lastSource = data\n    this.target.src = data\n  }\n  \n  async onSave(url) {\n    if (!url && this.target) {\n      return this.saveToTarget()\n    }\n    \n    url = url || this.getAttribute(\"src\") \n    if (url) {\n      this.setAttribute(\"src\", url)\n      this.saveFile()\n      lively.notify(\"saved \" + url)\n    } else {\n      this.onSaveAs()\n    }\n  }\n\n  async onSaveAs() {\n    var url = await lively.prompt(\"save as\", this.getAttribute(\"src\") || \"\")\n    if (url) {\n      this.onSave(url)\n    }    \n  }  \n  \n  async onOpen() {\n    var url = await lively.prompt(\"load\", this.getAttribute(\"src\") || \"\")\n    if (url) {\n      await this.loadImage(url)\n      lively.notify(\"load \" + url)\n    }\n  }\n\n  async onContextMenu(evt) {\n    const menuElements = [\n      [\"save\", () => this.onSave()],\n      [\"save as...\", () => this.onSaveAs()],\n      [\"open image\", () => this.onOpen()],\n    ];\n    const menu = new lively.contextmenu(this, menuElements)\n    menu.openIn(document.body, evt, this)\n  }\n  \n  livelyMigrate(other) {\n    this.target = other.target\n  }\n  \n  get lastSource() {\n    return this._lastSource  \n  }\n  \n  set lastSource(value) {\n    this._lastSource  = value\n    this.updateChangeIndicator()\n    \n  }\n  \n  updateChangeIndicator() {\n    if (!this.lastSource) return;\n    var newSource = this.canvas.toDataURL();\n    if (newSource !== this.lastSource) {\n      this.get(\"#changeIndicator\").style.backgroundColor = \"rgb(200,30,30)\";\n      this.textChanged = true;\n    } else {\n      this.get(\"#changeIndicator\").style.backgroundColor = \"rgb(200,200,200)\";\n      this.textChanged = false;\n    }\n  }\n  \n  async livelyExample() {\n    this.loadImage(\"https://lively-kernel.org/lively4/foo/test.png\")\n  }\n}\n"]}