{"version":3,"sources":["https://lively-kernel.org/lively4/BP2019RH1/components/group-chaining-widget.js"],"names":["assertListenerInterface","ReGL","GroupingLayouter","d3","Zoomer","Selector","IndividualsGrouper","Morph","ColorStore","DataProcessor","SelectAction","FilterAction","ColorAction","GroupAction","POINT_PADDING","GroupChainingWidget","initialize","listeners","name","regl","_createReglContextOnCanvas","canvasHeight","get","height","canvasWidth","width","nodes","transform","scale","zoomer","selector","updateNodes","drawNodes","drawZoomedPoints","points","animateNodes","duration","ease","easeCubic","timer","elapsed","t","Math","min","animateZoomedPoints","tick","stop","updateScale","updateTransform","setData","individuals","_initializeWithData","applyActionFromRootApplication","action","_dispatchAction","applyAction","isGlobal","_applyActionToListeners","lively","notify","addListener","listener","push","canvas","context","getContext","controlMenu","_registerControlWidget","individualsGrouper","_registerIndividualsGrouper","_start","initializeAfterDataFetch","groupingLayouter","forEach","_handleGroupAction","_handleColorAction","_handleSelectAction","_handleFilterAction","_handleNotSupportedAction","groupAction","addGrouping","attribute","colorAction","_recolorNodes","currentColorAttribute","node","nodeUniqueValue","getUniqueValueFromIndividual","data","colorString","getColorForValue","drawing","tcolor","convertRGBStringToReglColorObject","getGroupingStructure"],"mappings":"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","file":"group-chaining-widget.js","sourcesContent":["import { assertListenerInterface } from \"../src/internal/individuals-as-points/common/interfaces.js\";\nimport { ReGL } from \"../src/internal/individuals-as-points/common/regl-point-wrapper.js\"\nimport { GroupingLayouter } from \"../src/internal/individuals-as-points/group-chaining/grouping-layouter.js\"\nimport d3 from \"src/external/d3.v5.js\";\nimport { Zoomer } from \"../src/internal/individuals-as-points/group-chaining/zoomer.js\";\nimport { Selector } from \"../src/internal/individuals-as-points/group-chaining/selection-with-zoom.js\";\nimport { IndividualsGrouper } from \"../src/internal/individuals-as-points/group-chaining/individuals-grouper.js\";\nimport Morph from 'src/components/widgets/lively-morph.js'\n\nimport ColorStore from '../src/internal/individuals-as-points/common/color-store.js'\nimport DataProcessor from '../src/internal/individuals-as-points/common/data-processor.js'\n\nimport SelectAction from '../src/internal/individuals-as-points/common/actions/select-action.js'\nimport FilterAction from '../src/internal/individuals-as-points/common/actions/filter-action.js'\nimport ColorAction from '../src/internal/individuals-as-points/common/actions/color-action.js'\nimport GroupAction from '../src/internal/individuals-as-points/common/actions/group-action.js'\n\nconst POINT_PADDING = 3;\n\nexport default class GroupChainingWidget extends Morph {\n  async initialize() {\n    this.listeners = [];\n    \n    this.name = \"group-canvas-widget\";\n    this.regl = this._createReglContextOnCanvas();\n    \n    this.canvasHeight = this.get('#group-chaining-widget-canvas').height;\n    this.canvasWidth = this.get('#group-chaining-widget-canvas').width;\n    \n    this.nodes = null;\n  \n    this.transform = null;\n    this.scale = 1;\n    this.zoomer = new Zoomer(this);\n    this.selector = new Selector(this);\n  }\n  \n  \n  // ------------------------------------------\n  // Public Methods\n  // ------------------------------------------\n  \n  // *** Interface to IndividualsGrouper ***\n  \n  updateNodes(nodes){\n    this.nodes = nodes;\n  } \n  \n  drawNodes(){\n    this.regl.drawZoomedPoints(\n      {\n        points: this.nodes,\n        transform: this.transform,\n        scale: this.scale\n      });\n  }\n  \n  animateNodes() {\n\n    const duration = 2000;\n    const ease = d3.easeCubic;\n    let timer = d3.timer((elapsed) => {\n        const t = Math.min(1, ease(elapsed / duration))\n        this.regl.animateZoomedPoints({\n          points: this.nodes,\n          transform: this.transform,\n          scale: this.scale,\n          tick: t,\n        })\n\n        if (t === 1) {\n          timer.stop()\n        }\n      })\n  }\n  \n  // *** Interface to Zoomer *** \n  \n  updateScale(scale){\n    this.scale = scale;\n  }\n  \n  updateTransform(transform){\n    this.transform = transform;\n  }\n  \n  // *** Interface to application ***\n  \n  async setData(individuals) {\n    this.individuals = individuals;\n    await this._initializeWithData();\n  }\n  \n  applyActionFromRootApplication(action) {\n     this._dispatchAction(action);\n  }\n  \n  // *** Interface to control menu ***\n  \n  applyAction(action){\n    if(action.isGlobal){\n      this._applyActionToListeners(action);\n    } else {\n      this._dispatchAction(action);\n    }\n    \n    lively.notify(\"group-chaining received an action\")   \n    \n  }\n  \n  addListener(listener) {\n    assertListenerInterface(listener);\n    this.listeners.push(listener);\n  }\n  \n  // ------------------------------------------\n  // Private Methods\n  // ------------------------------------------\n  \n  _createReglContextOnCanvas(){\n    this.canvas = this.get(\"#group-chaining-widget-canvas\");\n    let context = this.canvas.getContext(\"webgl\"); \n    return new ReGL(context);\n  }\n  \n  _initializeWithData(){\n    this.controlMenu = this._registerControlWidget();\n    this.individualsGrouper = this._registerIndividualsGrouper();\n    \n    this._start()\n  }\n  \n  _registerControlWidget() {\n    let controlMenu = this.get(\"#group-chaining-widget-control-widget\");\n    controlMenu.addListener(this);\n    controlMenu.initializeAfterDataFetch();\n    \n    return controlMenu;\n  }\n  \n  _registerIndividualsGrouper(){\n    let groupingLayouter = new GroupingLayouter(this.canvasWidth, this.canvasHeight, POINT_PADDING);\n    let individualsGrouper = new IndividualsGrouper(this, this.individuals, groupingLayouter);\n    \n    return individualsGrouper;\n  }\n  \n  _applyActionToListeners(action){\n    this.listeners.forEach((listener) => {\n      listener.applyAction(action);\n    })\n  }\n  \n  _dispatchAction(action) {\n    switch(true) {\n      case (action instanceof GroupAction):\n        this._handleGroupAction(action);\n        break;\n      case (action instanceof ColorAction):\n        this._handleColorAction(action);\n        break;\n      case (action instanceof SelectAction):\n        this._handleSelectAction(action);\n        break;\n      case (action instanceof FilterAction):\n        this._handleFilterAction(action);\n        break;\n      default:\n        this._handleNotSupportedAction(action);\n     }\n  }\n  \n  _handleGroupAction(groupAction) {\n    this.individualsGrouper.addGrouping(groupAction.attribute);\n  }\n  \n  _handleColorAction(colorAction) {\n    this._recolorNodes(colorAction.attribute);\n    this.drawNodes();\n  }\n  \n  _recolorNodes(currentColorAttribute){\n    this.nodes.forEach((node) => {\n      let nodeUniqueValue = DataProcessor.getUniqueValueFromIndividual(node.data, currentColorAttribute)\n      let colorString = ColorStore.getColorForValue(currentColorAttribute, nodeUniqueValue);\n      node.drawing.tcolor = ColorStore.convertRGBStringToReglColorObject(colorString);\n    })\n  }\n  \n  _handleSelectAction(action) {\n    this.drawNodes();\n  }\n  \n  _handleNotSupportedAction(action) {\n    lively.notify(this.name + \" can't apply this action: \" + action.name);\n  }\n  \n  _handleFilterAction(action){\n    \n  }\n  \n  _start(){\n    this.nodes = this.individualsGrouper.getGroupingStructure();\n    this.drawNodes();\n  }\n\n}"]}