UNPKG

ng-zorro-antd

Version:

An enterprise-class UI components based on Ant Design and Angular

205 lines 35 kB
/** * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ import { drag } from 'd3-drag'; import { pointer, select } from 'd3-selection'; import { zoomIdentity } from 'd3-zoom'; const FRAC_VIEWPOINT_AREA = 0.8; export class Minimap { constructor(svg, zoomG, mainZoom, minimap, maxWidth, labelPadding) { this.svg = svg; this.labelPadding = labelPadding; this.zoomG = zoomG; this.mainZoom = mainZoom; this.maxWidth = maxWidth; const minimapElement = select(minimap); const minimapSvgElement = minimapElement.select('svg'); const viewpointElement = minimapSvgElement.select('rect'); this.canvas = minimapElement.select('canvas.viewport').node(); this.canvasRect = this.canvas.getBoundingClientRect(); const handleEvent = (event) => { const minimapOffset = this.minimapOffset(); const width = Number(viewpointElement.attr('width')); const height = Number(viewpointElement.attr('height')); const clickCoords = pointer(event, minimapSvgElement.node()); this.viewpointCoord.x = clickCoords[0] - width / 2 - minimapOffset.x; this.viewpointCoord.y = clickCoords[1] - height / 2 - minimapOffset.y; this.updateViewpoint(); }; this.viewpointCoord = { x: 0, y: 0 }; const dragEvent = drag().subject(Object).on('drag', handleEvent); viewpointElement.datum(this.viewpointCoord).call(dragEvent); // Make the minimap clickable. minimapSvgElement.on('click', event => { if (event.defaultPrevented) { // This click was part of a drag event, so suppress it. return; } handleEvent(event); }); this.viewpoint = viewpointElement.node(); this.minimapSvg = minimapSvgElement.node(); this.minimap = minimap; this.canvasBuffer = minimapElement.select('canvas.buffer').node(); this.update(); } minimapOffset() { return { x: (this.canvasRect.width - this.minimapSize.width) / 2, y: (this.canvasRect.height - this.minimapSize.height) / 2 }; } updateViewpoint() { // Update the coordinates of the viewpoint rectangle. select(this.viewpoint).attr('x', this.viewpointCoord.x).attr('y', this.viewpointCoord.y); // Update the translation vector of the main svg to reflect the // new viewpoint. const mainX = (-this.viewpointCoord.x * this.scaleMain) / this.scaleMinimap; const mainY = (-this.viewpointCoord.y * this.scaleMain) / this.scaleMinimap; select(this.svg).call(this.mainZoom.transform, zoomIdentity.translate(mainX, mainY).scale(this.scaleMain)); } update() { let sceneSize = null; try { // Get the size of the entire scene. sceneSize = this.zoomG.getBBox(); if (sceneSize.width === 0) { // There is no scene anymore. We have been detached from the dom. return; } } catch (e) { // Firefox produced NS_ERROR_FAILURE if we have been // detached from the dom. return; } const svgSelection = select(this.svg); // Read all the style rules in the document and embed them into the svg. // The svg needs to be self contained, i.e. all the style rules need to be // embedded so the canvas output matches the origin. let stylesText = ''; for (const k of new Array(document.styleSheets.length).keys()) { try { const cssRules = document.styleSheets[k].cssRules || document.styleSheets[k].rules; if (cssRules == null) { continue; } for (const i of new Array(cssRules.length).keys()) { // Remove tf-* selectors from the styles. stylesText += `${cssRules[i].cssText.replace(/ ?tf-[\w-]+ ?/g, '')}\n`; } } catch (e) { if (e.name !== 'SecurityError') { throw e; } } } // Temporarily add the css rules to the main svg. const svgStyle = svgSelection.append('style'); svgStyle.text(stylesText); // Temporarily remove the zoom/pan transform from the main svg since we // want the minimap to show a zoomed-out and centered view. const zoomGSelection = select(this.zoomG); const zoomTransform = zoomGSelection.attr('transform'); zoomGSelection.attr('transform', null); // Since we add padding, account for that here. sceneSize.height += this.labelPadding * 2; sceneSize.width += this.labelPadding * 2; // Temporarily assign an explicit width/height to the main svg, since // it doesn't have one (uses flex-box), but we need it for the canvas // to work. svgSelection.attr('width', sceneSize.width).attr('height', sceneSize.height); // Since the content inside the svg changed (e.g. a node was expanded), // the aspect ratio have also changed. Thus, we need to update the scale // factor of the minimap. The scale factor is determined such that both // the width and height of the minimap are <= maximum specified w/h. this.scaleMinimap = this.maxWidth / Math.max(sceneSize.width, sceneSize.height); this.minimapSize = { width: sceneSize.width * this.scaleMinimap, height: sceneSize.height * this.scaleMinimap }; const minimapOffset = this.minimapOffset(); // Update the size of the minimap's svg, the buffer canvas and the // viewpoint rect. select(this.minimapSvg).attr(this.minimapSize); select(this.canvasBuffer).attr(this.minimapSize); if (this.translate != null && this.zoom != null) { // Update the viewpoint rectangle shape since the aspect ratio of the // map has changed. requestAnimationFrame(() => this.zoom()); } // Serialize the main svg to a string which will be used as the rendering // content for the canvas. const svgXml = new XMLSerializer().serializeToString(this.svg); // Now that the svg is serialized for rendering, remove the temporarily // assigned styles, explicit width and height and bring back the pan/zoom // transform. svgStyle.remove(); svgSelection.attr('width', '100%').attr('height', '100%'); zoomGSelection.attr('transform', zoomTransform); const image = document.createElement('img'); image.onload = () => { // Draw the svg content onto the buffer canvas. const context = this.canvasBuffer.getContext('2d'); context.clearRect(0, 0, this.canvasBuffer.width, this.canvasBuffer.height); context.drawImage(image, minimapOffset.x, minimapOffset.y, this.minimapSize.width, this.minimapSize.height); requestAnimationFrame(() => { // Hide the old canvas and show the new buffer canvas. select(this.canvasBuffer).style('display', 'block'); select(this.canvas).style('display', 'none'); // Swap the two canvases. [this.canvas, this.canvasBuffer] = [this.canvasBuffer, this.canvas]; }); }; image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`; } /** * Handles changes in zooming/panning. Should be called from the main svg * to notify that a zoom/pan was performed and this minimap will update it's * viewpoint rectangle. * * @param transform */ zoom(transform) { if (this.scaleMinimap == null) { // Scene is not ready yet. return; } // Update the new translate and scale params, only if specified. if (transform) { this.translate = [transform.x, transform.y]; this.scaleMain = transform.k; } // Update the location of the viewpoint rectangle. const svgRect = this.svg.getBoundingClientRect(); const minimapOffset = this.minimapOffset(); const viewpointSelection = select(this.viewpoint); this.viewpointCoord.x = (-this.translate[0] * this.scaleMinimap) / this.scaleMain; this.viewpointCoord.y = (-this.translate[1] * this.scaleMinimap) / this.scaleMain; const viewpointWidth = (svgRect.width * this.scaleMinimap) / this.scaleMain; const viewpointHeight = (svgRect.height * this.scaleMinimap) / this.scaleMain; viewpointSelection .attr('x', this.viewpointCoord.x + minimapOffset.x) .attr('y', this.viewpointCoord.y + minimapOffset.y) .attr('width', viewpointWidth) .attr('height', viewpointHeight); // Show/hide the minimap depending on the viewpoint area as fraction of the // whole minimap. const mapWidth = this.minimapSize.width; const mapHeight = this.minimapSize.height; const x = this.viewpointCoord.x; const y = this.viewpointCoord.y; const w = Math.min(Math.max(0, x + viewpointWidth), mapWidth) - Math.min(Math.max(0, x), mapWidth); const h = Math.min(Math.max(0, y + viewpointHeight), mapHeight) - Math.min(Math.max(0, y), mapHeight); const fracIntersect = (w * h) / (mapWidth * mapHeight); if (fracIntersect < FRAC_VIEWPOINT_AREA) { this.minimap.classList.remove('hidden'); } else { this.minimap.classList.add('hidden'); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWluaW1hcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvZ3JhcGgvY29yZS9taW5pbWFwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDL0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDL0MsT0FBTyxFQUFnQixZQUFZLEVBQWlCLE1BQU0sU0FBUyxDQUFDO0FBTXBFLE1BQU0sbUJBQW1CLEdBQUcsR0FBRyxDQUFDO0FBRWhDLE1BQU0sT0FBTyxPQUFPO0lBbUJsQixZQUNFLEdBQWtCLEVBQ2xCLEtBQWtCLEVBQ2xCLFFBQTRDLEVBQzVDLE9BQW9CLEVBQ3BCLFFBQWdCLEVBQ2hCLFlBQW9CO1FBRXBCLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBQ2YsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbkIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0saUJBQWlCLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2RCxNQUFNLGdCQUFnQixHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsTUFBTSxHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxJQUFJLEVBQXVCLENBQUM7UUFDbkYsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFFdEQs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UUFBUSxHQUFHLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZELElBQUksYUFBYSxHQUFHLG1CQUFtQixFQUFFO1lBQ3ZDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUN6QzthQUFNO1lBQ0wsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ3RDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2dpdGh1Yi5jb20vTkctWk9SUk8vbmctem9ycm8tYW50ZC9ibG9iL21hc3Rlci9MSUNFTlNFXG4gKi9cblxuaW1wb3J0IHsgZHJhZyB9IGZyb20gJ2QzLWRyYWcnO1xuaW1wb3J0IHsgcG9pbnRlciwgc2VsZWN0IH0gZnJvbSAnZDMtc2VsZWN0aW9uJztcbmltcG9ydCB7IFpvb21CZWhhdmlvciwgem9vbUlkZW50aXR5LCBab29tVHJhbnNmb3JtIH0gZnJvbSAnZDMtem9vbSc7XG5cbmltcG9ydCB7IE56U2FmZUFueSB9IGZyb20gJ25nLXpvcnJvLWFudGQvY29yZS90eXBlcyc7XG5cbmltcG9ydCB7IE56Wm9vbVRyYW5zZm9ybSB9IGZyb20gJy4uL2ludGVyZmFjZSc7XG5cbmNvbnN0IEZSQUNfVklFV1BPSU5UX0FSRUEgPSAwLjg7XG5cbmV4cG9ydCBjbGFzcyBNaW5pbWFwIHtcbiAgcHJpdmF0ZSBtaW5pbWFwOiBIVE1MRWxlbWVudDtcbiAgcHJpdmF0ZSBjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50O1xuICBwcml2YXRlIGNhbnZhc1JlY3Q6IENsaWVudFJlY3Q7XG4gIHByaXZhdGUgY2FudmFzQnVmZmVyOiBIVE1MQ2FudmFzRWxlbWVudDtcbiAgcHJpdmF0ZSBtaW5pbWFwU3ZnOiBTVkdTVkdFbGVtZW50O1xuICBwcml2YXRlIHZpZXdwb2ludDogU1ZHUmVjdEVsZW1lbnQ7XG4gIHByaXZhdGUgc2NhbGVNaW5pbWFwITogbnVtYmVyO1xuICBwcml2YXRlIHNjYWxlTWFpbiE6IG51bWJlcjtcbiAgcHJpdmF0ZSBtYXhXaWR0aDogbnVtYmVyO1xuICBwcml2YXRlIHRyYW5zbGF0ZSE6IFtudW1iZXIsIG51bWJlcl07XG4gIHByaXZhdGUgdmlld3BvaW50Q29vcmQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfTtcbiAgcHJpdmF0ZSBtaW5pbWFwU2l6ZSE6IHsgd2lkdGg6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfTtcbiAgcHJpdmF0ZSBsYWJlbFBhZGRpbmc6IG51bWJlcjtcblxuICBwcml2YXRlIHN2ZzogU1ZHU1ZHRWxlbWVudDtcbiAgcHJpdmF0ZSB6b29tRzogU1ZHR0VsZW1lbnQ7XG4gIHByaXZhdGUgbWFpblpvb206IFpvb21CZWhhdmlvcjxOelNhZmVBbnksIE56U2FmZUFueT47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc3ZnOiBTVkdTVkdFbGVtZW50LFxuICAgIHpvb21HOiBTVkdHRWxlbWVudCxcbiAgICBtYWluWm9vbTogWm9vbUJlaGF2aW9yPE56U2FmZUFueSwgTnpTYWZlQW55PixcbiAgICBtaW5pbWFwOiBIVE1MRWxlbWVudCxcbiAgICBtYXhXaWR0aDogbnVtYmVyLFxuICAgIGxhYmVsUGFkZGluZzogbnVtYmVyXG4gICkge1xuICAgIHRoaXMuc3ZnID0gc3ZnO1xuICAgIHRoaXMubGFiZWxQYWRkaW5nID0gbGFiZWxQYWRkaW5nO1xuICAgIHRoaXMuem9vbUcgPSB6b29tRztcbiAgICB0aGlzLm1haW5ab29tID0gbWFpblpvb207XG4gICAgdGhpcy5tYXhXaWR0aCA9IG1heFdpZHRoO1xuICAgIGNvbnN0IG1pbmltYXBFbGVtZW50ID0gc2VsZWN0KG1pbmltYXApO1xuICAgIGNvbnN0IG1pbmltYXBTdmdFbGVtZW50ID0gbWluaW1hcEVsZW1lbnQuc2VsZWN0KCdzdmcnKTtcbiAgICBjb25zdCB2aWV3cG9pbnRFbGVtZW50ID0gbWluaW1hcFN2Z0VsZW1lbnQuc2VsZWN0KCdyZWN0Jyk7XG4gICAgdGhpcy5jYW52YXMgPSBtaW5pbWFwRWxlbWVudC5zZWxlY3QoJ2NhbnZhcy52aWV3cG9ydCcpLm5vZGUoKSBhcyBIVE1MQ2FudmFzRWxlbWVudDtcbiAgICB0aGlzLmNhbnZhc1JlY3QgPSB0aGlzLmNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIGNvbnN0IGhhbmRsZUV2ZW50ID0gKGV2ZW50OiBOelNhZmVBbnkpOiB2b2lkID0+IHtcbiAgICAgIGNvbnN0IG1pbmltYXBPZmZzZXQgPSB0aGlzLm1pbmltYXBPZmZzZXQoKTtcbiAgICAgIGNvbnN0IHdpZHRoID0gTnVtYmVyKHZpZXdwb2ludEVsZW1lbnQuYXR0cignd2lkdGgnKSk7XG4gICAgICBjb25zdCBoZWlnaHQgPSBOdW1iZXIodmlld3BvaW50RWxlbWVudC5hdHRyKCdoZWlnaHQnKSk7XG4gICAgICBjb25zdCBjbGlja0Nvb3JkcyA9IHBvaW50ZXIoZXZlbnQsIG1pbmltYXBTdmdFbGVtZW50Lm5vZGUoKSBhcyBOelNhZmVBbnkpO1xuICAgICAgdGhpcy52aWV3cG9pbnRDb29yZC54ID0gY2xpY2tDb29yZHNbMF0gLSB3aWR0aCAvIDIgLSBtaW5pbWFwT2Zmc2V0Lng7XG4gICAgICB0aGlzLnZpZXdwb2ludENvb3JkLnkgPSBjbGlja0Nvb3Jkc1sxXSAtIGhlaWdodCAvIDIgLSBtaW5pbWFwT2Zmc2V0Lnk7XG4gICAgICB0aGlzLnVwZGF0ZVZpZXdwb2ludCgpO1xuICAgIH07XG4gICAgdGhpcy52aWV3cG9pbnRDb29yZCA9IHsgeDogMCwgeTogMCB9O1xuICAgIGNvbnN0IGRyYWdFdmVudCA9IGRyYWcoKS5zdWJqZWN0KE9iamVjdCkub24oJ2RyYWcnLCBoYW5kbGVFdmVudCk7XG4gICAgdmlld3BvaW50RWxlbWVudC5kYXR1bSh0aGlzLnZpZXdwb2ludENvb3JkIGFzIE56U2FmZUFueSkuY2FsbChkcmFnRXZlbnQgYXMgTnpTYWZlQW55KTtcblxuICAgIC8vIE1ha2UgdGhlIG1pbmltYXAgY2xpY2thYmxlLlxuICAgIG1pbmltYXBTdmdFbGVtZW50Lm9uKCdjbGljaycsIGV2ZW50ID0+IHtcbiAgICAgIGlmICgoZXZlbnQgYXMgRXZlbnQpLmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgLy8gVGhpcyBjbGljayB3YXMgcGFydCBvZiBhIGRyYWcgZXZlbnQsIHNvIHN1cHByZXNzIGl0LlxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBoYW5kbGVFdmVudChldmVudCk7XG4gICAgfSk7XG4gICAgdGhpcy52aWV3cG9pbnQgPSB2aWV3cG9pbnRFbGVtZW50Lm5vZGUoKSBhcyBTVkdSZWN0RWxlbWVudDtcbiAgICB0aGlzLm1pbmltYXBTdmcgPSBtaW5pbWFwU3ZnRWxlbWVudC5ub2RlKCkgYXMgU1ZHU1ZHRWxlbWVudDtcbiAgICB0aGlzLm1pbmltYXAgPSBtaW5pbWFwO1xuICAgIHRoaXMuY2FudmFzQnVmZmVyID0gbWluaW1hcEVsZW1lbnQuc2VsZWN0KCdjYW52YXMuYnVmZmVyJykubm9kZSgpIGFzIEhUTUxDYW52YXNFbGVtZW50O1xuICAgIHRoaXMudXBkYXRlKCk7XG4gIH1cblxuICBwcml2YXRlIG1pbmltYXBPZmZzZXQoKTogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHtcbiAgICByZXR1cm4ge1xuICAgICAgeDogKHRoaXMuY2FudmFzUmVjdC53aWR0aCAtIHRoaXMubWluaW1hcFNpemUud2lkdGgpIC8gMixcbiAgICAgIHk6ICh0aGlzLmNhbnZhc1JlY3QuaGVpZ2h0IC0gdGhpcy5taW5pbWFwU2l6ZS5oZWlnaHQpIC8gMlxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVZpZXdwb2ludCgpOiB2b2lkIHtcbiAgICAvLyBVcGRhdGUgdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSB2aWV3cG9pbnQgcmVjdGFuZ2xlLlxuICAgIHNlbGVjdCh0aGlzLnZpZXdwb2ludCkuYXR0cigneCcsIHRoaXMudmlld3BvaW50Q29vcmQueCkuYXR0cigneScsIHRoaXMudmlld3BvaW50Q29vcmQueSk7XG4gICAgLy8gVXBkYXRlIHRoZSB0cmFuc2xhdGlvbiB2ZWN0b3Igb2YgdGhlIG1haW4gc3ZnIHRvIHJlZmxlY3QgdGhlXG4gICAgLy8gbmV3IHZpZXdwb2ludC5cbiAgICBjb25zdCBtYWluWCA9ICgtdGhpcy52aWV3cG9pbnRDb29yZC54ICogdGhpcy5zY2FsZU1haW4pIC8gdGhpcy5zY2FsZU1pbmltYXA7XG4gICAgY29uc3QgbWFpblkgPSAoLXRoaXMudmlld3BvaW50Q29vcmQueSAqIHRoaXMuc2NhbGVNYWluKSAvIHRoaXMuc2NhbGVNaW5pbWFwO1xuICAgIHNlbGVjdCh0aGlzLnN2ZykuY2FsbCh0aGlzLm1haW5ab29tLnRyYW5zZm9ybSwgem9vbUlkZW50aXR5LnRyYW5zbGF0ZShtYWluWCwgbWFpblkpLnNjYWxlKHRoaXMuc2NhbGVNYWluKSk7XG4gIH1cblxuICB1cGRhdGUoKTogdm9pZCB7XG4gICAgbGV0IHNjZW5lU2l6ZSA9IG51bGw7XG4gICAgdHJ5IHtcbiAgICAgIC8vIEdldCB0aGUgc2l6ZSBvZiB0aGUgZW50aXJlIHNjZW5lLlxuICAgICAgc2NlbmVTaXplID0gdGhpcy56b29tRy5nZXRCQm94KCk7XG4gICAgICBpZiAoc2NlbmVTaXplLndpZHRoID09PSAwKSB7XG4gICAgICAgIC8vIFRoZXJlIGlzIG5vIHNjZW5lIGFueW1vcmUuIFdlIGhhdmUgYmVlbiBkZXRhY2hlZCBmcm9tIHRoZSBkb20uXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBGaXJlZm94IHByb2R1Y2VkIE5TX0VSUk9SX0ZBSUxVUkUgaWYgd2UgaGF2ZSBiZWVuXG4gICAgICAvLyBkZXRhY2hlZCBmcm9tIHRoZSBkb20uXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc3ZnU2VsZWN0aW9uID0gc2VsZWN0KHRoaXMuc3ZnKTtcbiAgICAvLyBSZWFkIGFsbCB0aGUgc3R5bGUgcnVsZXMgaW4gdGhlIGRvY3VtZW50IGFuZCBlbWJlZCB0aGVtIGludG8gdGhlIHN2Zy5cbiAgICAvLyBUaGUgc3ZnIG5lZWRzIHRvIGJlIHNlbGYgY29udGFpbmVkLCBpLmUuIGFsbCB0aGUgc3R5bGUgcnVsZXMgbmVlZCB0byBiZVxuICAgIC8vIGVtYmVkZGVkIHNvIHRoZSBjYW52YXMgb3V0cHV0IG1hdGNoZXMgdGhlIG9yaWdpbi5cbiAgICBsZXQgc3R5bGVzVGV4dCA9ICcnO1xuXG4gICAgZm9yIChjb25zdCBrIG9mIG5ldyBBcnJheShkb2N1bWVudC5zdHlsZVNoZWV0cy5sZW5ndGgpLmtleXMoKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY3NzUnVsZXMgPVxuICAgICAgICAgIChkb2N1bWVudC5zdHlsZVNoZWV0c1trXSBhcyBOelNhZmVBbnkpLmNzc1J1bGVzIHx8IChkb2N1bWVudC5zdHlsZVNoZWV0c1trXSBhcyBOelNhZmVBbnkpLnJ1bGVzO1xuICAgICAgICBpZiAoY3NzUnVsZXMgPT0gbnVsbCkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgaSBvZiBuZXcgQXJyYXkoY3NzUnVsZXMubGVuZ3RoKS5rZXlzKCkpIHtcbiAgICAgICAgICAvLyBSZW1vdmUgdGYtKiBzZWxlY3RvcnMgZnJvbSB0aGUgc3R5bGVzLlxuICAgICAgICAgIHN0eWxlc1RleHQgKz0gYCR7Y3NzUnVsZXNbaV0uY3NzVGV4dC5yZXBsYWNlKC8gP3RmLVtcXHctXSsgPy9nLCAnJyl9XFxuYDtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZS5uYW1lICE9PSAnU2VjdXJpdHlFcnJvcicpIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGVtcG9yYXJpbHkgYWRkIHRoZSBjc3MgcnVsZXMgdG8gdGhlIG1haW4gc3ZnLlxuICAgIGNvbnN0IHN2Z1N0eWxlID0gc3ZnU2VsZWN0aW9uLmFwcGVuZCgnc3R5bGUnKTtcbiAgICBzdmdTdHlsZS50ZXh0KHN0eWxlc1RleHQpO1xuXG4gICAgLy8gVGVtcG9yYXJpbHkgcmVtb3ZlIHRoZSB6b29tL3BhbiB0cmFuc2Zvcm0gZnJvbSB0aGUgbWFpbiBzdmcgc2luY2Ugd2VcbiAgICAvLyB3YW50IHRoZSBtaW5pbWFwIHRvIHNob3cgYSB6b29tZWQtb3V0IGFuZCBjZW50ZXJlZCB2aWV3LlxuICAgIGNvbnN0IHpvb21HU2VsZWN0aW9uID0gc2VsZWN0KHRoaXMuem9vbUcpO1xuICAgIGNvbnN0IHpvb21UcmFuc2Zvcm0gPSB6b29tR1NlbGVjdGlvbi5hdHRyKCd0cmFuc2Zvcm0nKTtcbiAgICB6b29tR1NlbGVjdGlvbi5hdHRyKCd0cmFuc2Zvcm0nLCBudWxsKTtcblxuICAgIC8vIFNpbmNlIHdlIGFkZCBwYWRkaW5nLCBhY2NvdW50IGZvciB0aGF0IGhlcmUuXG4gICAgc2NlbmVTaXplLmhlaWdodCArPSB0aGlzLmxhYmVsUGFkZGluZyAqIDI7XG4gICAgc2NlbmVTaXplLndpZHRoICs9IHRoaXMubGFiZWxQYWRkaW5nICogMjtcblxuICAgIC8vIFRlbXBvcmFyaWx5IGFzc2lnbiBhbiBleHBsaWNpdCB3aWR0aC9oZWlnaHQgdG8gdGhlIG1haW4gc3ZnLCBzaW5jZVxuICAgIC8vIGl0IGRvZXNuJ3QgaGF2ZSBvbmUgKHVzZXMgZmxleC1ib3gpLCBidXQgd2UgbmVlZCBpdCBmb3IgdGhlIGNhbnZhc1xuICAgIC8vIHRvIHdvcmsuXG4gICAgc3ZnU2VsZWN0aW9uLmF0dHIoJ3dpZHRoJywgc2NlbmVTaXplLndpZHRoKS5hdHRyKCdoZWlnaHQnLCBzY2VuZVNpemUuaGVpZ2h0KTtcblxuICAgIC8vIFNpbmNlIHRoZSBjb250ZW50IGluc2lkZSB0aGUgc3ZnIGNoYW5nZWQgKGUuZy4gYSBub2RlIHdhcyBleHBhbmRlZCksXG4gICAgLy8gdGhlIGFzcGVjdCByYXRpbyBoYXZlIGFsc28gY2hhbmdlZC4gVGh1cywgd2UgbmVlZCB0byB1cGRhdGUgdGhlIHNjYWxlXG4gICAgLy8gZmFjdG9yIG9mIHRoZSBtaW5pbWFwLiBUaGUgc2NhbGUgZmFjdG9yIGlzIGRldGVybWluZWQgc3VjaCB0aGF0IGJvdGhcbiAgICAvLyB0aGUgd2lkdGggYW5kIGhlaWdodCBvZiB0aGUgbWluaW1hcCBhcmUgPD0gbWF4aW11bSBzcGVjaWZpZWQgdy9oLlxuICAgIHRoaXMuc2NhbGVNaW5pbWFwID0gdGhpcy5tYXhXaWR0aCAvIE1hdGgubWF4KHNjZW5lU2l6ZS53aWR0aCwgc2NlbmVTaXplLmhlaWdodCk7XG4gICAgdGhpcy5taW5pbWFwU2l6ZSA9IHtcbiAgICAgIHdpZHRoOiBzY2VuZVNpemUud2lkdGggKiB0aGlzLnNjYWxlTWluaW1hcCxcbiAgICAgIGhlaWdodDogc2NlbmVTaXplLmhlaWdodCAqIHRoaXMuc2NhbGVNaW5pbWFwXG4gICAgfTtcblxuICAgIGNvbnN0IG1pbmltYXBPZmZzZXQgPSB0aGlzLm1pbmltYXBPZmZzZXQoKTtcblxuICAgIC8vIFVwZGF0ZSB0aGUgc2l6ZSBvZiB0aGUgbWluaW1hcCdzIHN2ZywgdGhlIGJ1ZmZlciBjYW52YXMgYW5kIHRoZVxuICAgIC8vIHZpZXdwb2ludCByZWN0LlxuICAgIHNlbGVjdCh0aGlzLm1pbmltYXBTdmcpLmF0dHIodGhpcy5taW5pbWFwU2l6ZSBhcyBOelNhZmVBbnkpO1xuICAgIHNlbGVjdCh0aGlzLmNhbnZhc0J1ZmZlcikuYXR0cih0aGlzLm1pbmltYXBTaXplIGFzIE56U2FmZUFueSk7XG5cbiAgICBpZiAodGhpcy50cmFuc2xhdGUgIT0gbnVsbCAmJiB0aGlzLnpvb20gIT0gbnVsbCkge1xuICAgICAgLy8gVXBkYXRlIHRoZSB2aWV3cG9pbnQgcmVjdGFuZ2xlIHNoYXBlIHNpbmNlIHRoZSBhc3BlY3QgcmF0aW8gb2YgdGhlXG4gICAgICAvLyBtYXAgaGFzIGNoYW5nZWQuXG4gICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gdGhpcy56b29tKCkpO1xuICAgIH1cblxuICAgIC8vIFNlcmlhbGl6ZSB0aGUgbWFpbiBzdmcgdG8gYSBzdHJpbmcgd2hpY2ggd2lsbCBiZSB1c2VkIGFzIHRoZSByZW5kZXJpbmdcbiAgICAvLyBjb250ZW50IGZvciB0aGUgY2FudmFzLlxuICAgIGNvbnN0IHN2Z1htbCA9IG5ldyBYTUxTZXJpYWxpemVyKCkuc2VyaWFsaXplVG9TdHJpbmcodGhpcy5zdmcpO1xuXG4gICAgLy8gTm93IHRoYXQgdGhlIHN2ZyBpcyBzZXJpYWxpemVkIGZvciByZW5kZXJpbmcsIHJlbW92ZSB0aGUgdGVtcG9yYXJpbHlcbiAgICAvLyBhc3NpZ25lZCBzdHlsZXMsIGV4cGxpY2l0IHdpZHRoIGFuZCBoZWlnaHQgYW5kIGJyaW5nIGJhY2sgdGhlIHBhbi96b29tXG4gICAgLy8gdHJhbnNmb3JtLlxuICAgIHN2Z1N0eWxlLnJlbW92ZSgpO1xuICAgIHN2Z1NlbGVjdGlvbi5hdHRyKCd3aWR0aCcsICcxMDAlJykuYXR0cignaGVpZ2h0JywgJzEwMCUnKTtcblxuICAgIHpvb21HU2VsZWN0aW9uLmF0dHIoJ3RyYW5zZm9ybScsIHpvb21UcmFuc2Zvcm0pO1xuXG4gICAgY29uc3QgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAvLyBEcmF3IHRoZSBzdmcgY29udGVudCBvbnRvIHRoZSBidWZmZXIgY2FudmFzLlxuICAgICAgY29uc3QgY29udGV4dCA9IHRoaXMuY2FudmFzQnVmZmVyLmdldENvbnRleHQoJzJkJyk7XG4gICAgICBjb250ZXh0IS5jbGVhclJlY3QoMCwgMCwgdGhpcy5jYW52YXNCdWZmZXIud2lkdGgsIHRoaXMuY2FudmFzQnVmZmVyLmhlaWdodCk7XG5cbiAgICAgIGNvbnRleHQhLmRyYXdJbWFnZShpbWFnZSwgbWluaW1hcE9mZnNldC54LCBtaW5pbWFwT2Zmc2V0LnksIHRoaXMubWluaW1hcFNpemUud2lkdGgsIHRoaXMubWluaW1hcFNpemUuaGVpZ2h0KTtcbiAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgIC8vIEhpZGUgdGhlIG9sZCBjYW52YXMgYW5kIHNob3cgdGhlIG5ldyBidWZmZXIgY2FudmFzLlxuICAgICAgICBzZWxlY3QodGhpcy5jYW52YXNCdWZmZXIpLnN0eWxlKCdkaXNwbGF5JywgJ2Jsb2NrJyk7XG4gICAgICAgIHNlbGVjdCh0aGlzLmNhbnZhcykuc3R5bGUoJ2Rpc3BsYXknLCAnbm9uZScpO1xuICAgICAgICAvLyBTd2FwIHRoZSB0d28gY2FudmFzZXMuXG4gICAgICAgIFt0aGlzLmNhbnZhcywgdGhpcy5jYW52YXNCdWZmZXJdID0gW3RoaXMuY2FudmFzQnVmZmVyLCB0aGlzLmNhbnZhc107XG4gICAgICB9KTtcbiAgICB9O1xuICAgIGltYWdlLnNyYyA9IGBkYXRhOmltYWdlL3N2Zyt4bWw7Y2hhcnNldD11dGYtOCwke2VuY29kZVVSSUNvbXBvbmVudChzdmdYbWwpfWA7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyBjaGFuZ2VzIGluIHpvb21pbmcvcGFubmluZy4gU2hvdWxkIGJlIGNhbGxlZCBmcm9tIHRoZSBtYWluIHN2Z1xuICAgKiB0byBub3RpZnkgdGhhdCBhIHpvb20vcGFuIHdhcyBwZXJmb3JtZWQgYW5kIHRoaXMgbWluaW1hcCB3aWxsIHVwZGF0ZSBpdCdzXG4gICAqIHZpZXdwb2ludCByZWN0YW5nbGUuXG4gICAqXG4gICAqIEBwYXJhbSB0cmFuc2Zvcm1cbiAgICovXG4gIHpvb20odHJhbnNmb3JtPzogWm9vbVRyYW5zZm9ybSB8IE56Wm9vbVRyYW5zZm9ybSk6IHZvaWQge1xuICAgIGlmICh0aGlzLnNjYWxlTWluaW1hcCA9PSBudWxsKSB7XG4gICAgICAvLyBTY2VuZSBpcyBub3QgcmVhZHkgeWV0LlxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBVcGRhdGUgdGhlIG5ldyB0cmFuc2xhdGUgYW5kIHNjYWxlIHBhcmFtcywgb25seSBpZiBzcGVjaWZpZWQuXG4gICAgaWYgKHRyYW5zZm9ybSkge1xuICAgICAgdGhpcy50cmFuc2xhdGUgPSBbdHJhbnNmb3JtLngsIHRyYW5zZm9ybS55XTtcbiAgICAgIHRoaXMuc2NhbGVNYWluID0gdHJhbnNmb3JtLms7XG4gICAgfVxuXG4gICAgLy8gVXBkYXRlIHRoZSBsb2NhdGlvbiBvZiB0aGUgdmlld3BvaW50IHJlY3RhbmdsZS5cbiAgICBjb25zdCBzdmdSZWN0ID0gdGhpcy5zdmcuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgbWluaW1hcE9mZnNldCA9IHRoaXMubWluaW1hcE9mZnNldCgpO1xuICAgIGNvbnN0IHZpZXdwb2ludFNlbGVjdGlvbiA9IHNlbGVjdCh0aGlzLnZpZXdwb2ludCk7XG4gICAgdGhpcy52aWV3cG9pbnRDb29yZC54ID0gKC10aGlzLnRyYW5zbGF0ZVswXSAqIHRoaXMuc2NhbGVNaW5pbWFwKSAvIHRoaXMuc2NhbGVNYWluO1xuICAgIHRoaXMudmlld3BvaW50Q29vcmQueSA9ICgtdGhpcy50cmFuc2xhdGVbMV0gKiB0aGlzLnNjYWxlTWluaW1hcCkgLyB0aGlzLnNjYWxlTWFpbjtcbiAgICBjb25zdCB2aWV3cG9pbnRXaWR0aCA9IChzdmdSZWN0LndpZHRoICogdGhpcy5zY2FsZU1pbmltYXApIC8gdGhpcy5zY2FsZU1haW47XG4gICAgY29uc3Qgdmlld3BvaW50SGVpZ2h0ID0gKHN2Z1JlY3QuaGVpZ2h0ICogdGhpcy5zY2FsZU1pbmltYXApIC8gdGhpcy5zY2FsZU1haW47XG4gICAgdmlld3BvaW50U2VsZWN0aW9uXG4gICAgICAuYXR0cigneCcsIHRoaXMudmlld3BvaW50Q29vcmQueCArIG1pbmltYXBPZmZzZXQueClcbiAgICAgIC5hdHRyKCd5JywgdGhpcy52aWV3cG9pbnRDb29yZC55ICsgbWluaW1hcE9mZnNldC55KVxuICAgICAgLmF0dHIoJ3dpZHRoJywgdmlld3BvaW50V2lkdGgpXG4gICAgICAuYXR0cignaGVpZ2h0Jywgdmlld3BvaW50SGVpZ2h0KTtcbiAgICAvLyBTaG93L2hpZGUgdGhlIG1pbmltYXAgZGVwZW5kaW5nIG9uIHRoZSB2aWV3cG9pbnQgYXJlYSBhcyBmcmFjdGlvbiBvZiB0aGVcbiAgICAvLyB3aG9sZSBtaW5pbWFwLlxuICAgIGNvbnN0IG1hcFdpZHRoID0gdGhpcy5taW5pbWFwU2l6ZS53aWR0aDtcbiAgICBjb25zdCBtYXBIZWlnaHQgPSB0aGlzLm1pbmltYXBTaXplLmhlaWdodDtcbiAgICBjb25zdCB4ID0gdGhpcy52aWV3cG9pbnRDb29yZC54O1xuICAgIGNvbnN0IHkgPSB0aGlzLnZpZXdwb2ludENvb3JkLnk7XG4gICAgY29uc3QgdyA9IE1hdGgubWluKE1hdGgubWF4KDAsIHggKyB2aWV3cG9pbnRXaWR0aCksIG1hcFdpZHRoKSAtIE1hdGgubWluKE1hdGgubWF4KDAsIHgpLCBtYXBXaWR0aCk7XG4gICAgY29uc3QgaCA9IE1hdGgubWluKE1hdGgubWF4KDAsIHkgKyB2aWV3cG9pbnRIZWlnaHQpLCBtYXBIZWlnaHQpIC0gTWF0aC5taW4oTWF0aC5tYXgoMCwgeSksIG1hcEhlaWdodCk7XG4gICAgY29uc3QgZnJhY0ludGVyc2VjdCA9ICh3ICogaCkgLyAobWFwV2lkdGggKiBtYXBIZWlnaHQpO1xuICAgIGlmIChmcmFjSW50ZXJzZWN0IDwgRlJBQ19WSUVXUE9JTlRfQVJFQSkge1xuICAgICAgdGhpcy5taW5pbWFwLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1pbmltYXAuY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7XG4gICAgfVxuICB9XG59XG4iXX0=