UNPKG

ng-zorro-antd

Version:

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

224 lines 37 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'; import { reqAnimFrame } from 'ng-zorro-antd/core/polyfill'; const FRAC_VIEWPOINT_AREA = 0.8; export class Minimap { constructor(ngZone, svg, zoomG, mainZoom, minimap, maxWidth, labelPadding) { this.ngZone = ngZone; this.svg = svg; this.zoomG = zoomG; this.mainZoom = mainZoom; this.minimap = minimap; this.maxWidth = maxWidth; this.labelPadding = labelPadding; this.unlisteners = []; 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 subject = drag().subject(Object); const dragEvent = subject.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.unlisteners.push(() => { subject.on('drag', null); minimapSvgElement.on('click', null); }); this.viewpoint = viewpointElement.node(); this.minimapSvg = minimapSvgElement.node(); this.canvasBuffer = minimapElement.select('canvas.buffer').node(); this.update(); } destroy() { while (this.unlisteners.length) { this.unlisteners.pop()(); } } 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. this.ngZone.runOutsideAngular(() => reqAnimFrame(() => 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'); const 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); this.ngZone.runOutsideAngular(() => { reqAnimFrame(() => { // 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.addEventListener('load', onLoad); image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`; this.unlisteners.push(() => { image.removeEventListener('load', onLoad); }); } /** * 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWluaW1hcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvZ3JhcGgvY29yZS9taW5pbWFwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUlILE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDL0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDL0MsT0FBTyxFQUFnQixZQUFZLEVBQWlCLE1BQU0sU0FBUyxDQUFDO0FBRXBFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUszRCxNQUFNLG1CQUFtQixHQUFHLEdBQUcsQ0FBQztBQUVoQyxNQUFNLE9BQU8sT0FBTztJQWNsQixZQUNVLE1BQWMsRUFDZCxHQUFrQixFQUNsQixLQUFrQixFQUNsQixRQUE0QyxFQUM1QyxPQUFvQixFQUNwQixRQUFnQixFQUNoQixZQUFvQjtRQU5wQixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2QsUUFBRyxHQUFILEdBQUcsQ0FBZTtRQUNsQixVQUFLLEdBQUwsS0FBSyxDQUFhO1FBQ2xCLGFBQVEsR0FBUixRQUFRLENBQW9DO1FBQzVDLFlBQU8sR0FBUCxPQUFPLENBQWE7UUFDcEIsYUFBUSxHQUFSLFFBQVEsQ0FBUTtRQUNoQixpQkFBWSxHQUFaLFlBQVksQ0FBUTtRQVR0QixnQkFBVyxHQUFtQixFQUFFLENBQUM7UUFXdkMsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0saUJBQWlCLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2RCxNQUFNLGdCQUFnQixHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsTUFBTSxHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxJ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dXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9ORy1aT1JSTy9uZy16b3Jyby1hbnRkL2Jsb2IvbWFzdGVyL0xJQ0VOU0VcbiAqL1xuXG5pbXBvcnQgeyBOZ1pvbmUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgZHJhZyB9IGZyb20gJ2QzLWRyYWcnO1xuaW1wb3J0IHsgcG9pbnRlciwgc2VsZWN0IH0gZnJvbSAnZDMtc2VsZWN0aW9uJztcbmltcG9ydCB7IFpvb21CZWhhdmlvciwgem9vbUlkZW50aXR5LCBab29tVHJhbnNmb3JtIH0gZnJvbSAnZDMtem9vbSc7XG5cbmltcG9ydCB7IHJlcUFuaW1GcmFtZSB9IGZyb20gJ25nLXpvcnJvLWFudGQvY29yZS9wb2x5ZmlsbCc7XG5pbXBvcnQgeyBOelNhZmVBbnkgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvdHlwZXMnO1xuXG5pbXBvcnQgeyBOelpvb21UcmFuc2Zvcm0gfSBmcm9tICcuLi9pbnRlcmZhY2UnO1xuXG5jb25zdCBGUkFDX1ZJRVdQT0lOVF9BUkVBID0gMC44O1xuXG5leHBvcnQgY2xhc3MgTWluaW1hcCB7XG4gIHByaXZhdGUgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudDtcbiAgcHJpdmF0ZSBjYW52YXNSZWN0OiBDbGllbnRSZWN0O1xuICBwcml2YXRlIGNhbnZhc0J1ZmZlcjogSFRNTENhbnZhc0VsZW1lbnQ7XG4gIHByaXZhdGUgbWluaW1hcFN2ZzogU1ZHU1ZHRWxlbWVudDtcbiAgcHJpdmF0ZSB2aWV3cG9pbnQ6IFNWR1JlY3RFbGVtZW50O1xuICBwcml2YXRlIHNjYWxlTWluaW1hcCE6IG51bWJlcjtcbiAgcHJpdmF0ZSBzY2FsZU1haW4hOiBudW1iZXI7XG4gIHByaXZhdGUgdHJhbnNsYXRlITogW251bWJlciwgbnVtYmVyXTtcbiAgcHJpdmF0ZSB2aWV3cG9pbnRDb29yZDogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9O1xuICBwcml2YXRlIG1pbmltYXBTaXplITogeyB3aWR0aDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9O1xuXG4gIHByaXZhdGUgdW5saXN0ZW5lcnM6IFZvaWRGdW5jdGlvbltdID0gW107XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIHN2ZzogU1ZHU1ZHRWxlbWVudCxcbiAgICBwcml2YXRlIHpvb21HOiBTVkdHRWxlbWVudCxcbiAgICBwcml2YXRlIG1haW5ab29tOiBab29tQmVoYXZpb3I8TnpTYWZlQW55LCBOelNhZmVBbnk+LFxuICAgIHByaXZhdGUgbWluaW1hcDogSFRNTEVsZW1lbnQsXG4gICAgcHJpdmF0ZSBtYXhXaWR0aDogbnVtYmVyLFxuICAgIHByaXZhdGUgbGFiZWxQYWRkaW5nOiBudW1iZXJcbiAgKSB7XG4gICAgY29uc3QgbWluaW1hcEVsZW1lbnQgPSBzZWxlY3QobWluaW1hcCk7XG4gICAgY29uc3QgbWluaW1hcFN2Z0VsZW1lbnQgPSBtaW5pbWFwRWxlbWVudC5zZWxlY3QoJ3N2ZycpO1xuICAgIGNvbnN0IHZpZXdwb2ludEVsZW1lbnQgPSBtaW5pbWFwU3ZnRWxlbWVudC5zZWxlY3QoJ3JlY3QnKTtcbiAgICB0aGlzLmNhbnZhcyA9IG1pbmltYXBFbGVtZW50LnNlbGVjdCgnY2FudmFzLnZpZXdwb3J0Jykubm9kZSgpIGFzIEhUTUxDYW52YXNFbGVtZW50O1xuICAgIHRoaXMuY2FudmFzUmVjdCA9IHRoaXMuY2FudmFzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgY29uc3QgaGFuZGxlRXZlbnQgPSAoZXZlbnQ6IE56U2FmZUFueSk6IHZvaWQgPT4ge1xuICAgICAgY29uc3QgbWluaW1hcE9mZnNldCA9IHRoaXMubWluaW1hcE9mZnNldCgpO1xuICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIodmlld3BvaW50RWxlbWVudC5hdHRyKCd3aWR0aCcpKTtcbiAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih2aWV3cG9pbnRFbGVtZW50LmF0dHIoJ2hlaWdodCcpKTtcbiAgICAgIGNvbnN0IGNsaWNrQ29vcmRzID0gcG9pbnRlcihldmVudCwgbWluaW1hcFN2Z0VsZW1lbnQubm9kZSgpIGFzIE56U2FmZUFueSk7XG4gICAgICB0aGlzLnZpZXdwb2ludENvb3JkLnggPSBjbGlja0Nvb3Jkc1swXSAtIHdpZHRoIC8gMiAtIG1pbmltYXBPZmZzZXQueDtcbiAgICAgIHRoaXMudmlld3BvaW50Q29vcmQueSA9IGNsaWNrQ29vcmRzWzFdIC0gaGVpZ2h0IC8gMiAtIG1pbmltYXBPZmZzZXQueTtcbiAgICAgIHRoaXMudXBkYXRlVmlld3BvaW50KCk7XG4gICAgfTtcbiAgICB0aGlzLnZpZXdwb2ludENvb3JkID0geyB4OiAwLCB5OiAwIH07XG4gICAgY29uc3Qgc3ViamVjdCA9IGRyYWcoKS5zdWJqZWN0KE9iamVjdCk7XG4gICAgY29uc3QgZHJhZ0V2ZW50ID0gc3ViamVjdC5vbignZHJhZycsIGhhbmRsZUV2ZW50KTtcbiAgICB2aWV3cG9pbnRFbGVtZW50LmRhdHVtKHRoaXMudmlld3BvaW50Q29vcmQgYXMgTnpTYWZlQW55KS5jYWxsKGRyYWdFdmVudCBhcyBOelNhZmVBbnkpO1xuXG4gICAgLy8gTWFrZSB0aGUgbWluaW1hcCBjbGlja2FibGUuXG4gICAgbWluaW1hcFN2Z0VsZW1lbnQub24oJ2NsaWNrJywgZXZlbnQgPT4ge1xuICAgICAgaWYgKChldmVudCBhcyBFdmVudCkuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAvLyBUaGlzIGNsaWNrIHdhcyBwYXJ0IG9mIGEgZHJhZyBldmVudCwgc28gc3VwcHJlc3MgaXQuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGhhbmRsZUV2ZW50KGV2ZW50KTtcbiAgICB9KTtcbiAgICB0aGlzLnVubGlzdGVuZXJzLnB1c2goKCkgPT4ge1xuICAgICAgc3ViamVjdC5vbignZHJhZycsIG51bGwpO1xuICAgICAgbWluaW1hcFN2Z0VsZW1lbnQub24oJ2NsaWNrJywgbnVsbCk7XG4gICAgfSk7XG4gICAgdGhpcy52aWV3cG9pbnQgPSB2aWV3cG9pbnRFbGVtZW50Lm5vZGUoKSBhcyBTVkdSZWN0RWxlbWVudDtcbiAgICB0aGlzLm1pbmltYXBTdmcgPSBtaW5pbWFwU3ZnRWxlbWVudC5ub2RlKCkgYXMgU1ZHU1ZHRWxlbWVudDtcbiAgICB0aGlzLmNhbnZhc0J1ZmZlciA9IG1pbmltYXBFbGVtZW50LnNlbGVjdCgnY2FudmFzLmJ1ZmZlcicpLm5vZGUoKSBhcyBIVE1MQ2FudmFzRWxlbWVudDtcbiAgICB0aGlzLnVwZGF0ZSgpO1xuICB9XG5cbiAgZGVzdHJveSgpOiB2b2lkIHtcbiAgICB3aGlsZSAodGhpcy51bmxpc3RlbmVycy5sZW5ndGgpIHtcbiAgICAgIHRoaXMudW5saXN0ZW5lcnMucG9wKCkhKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtaW5pbWFwT2Zmc2V0KCk6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6ICh0aGlzLmNhbnZhc1JlY3Qud2lkdGggLSB0aGlzLm1pbmltYXBTaXplLndpZHRoKSAvIDIsXG4gICAgICB5OiAodGhpcy5jYW52YXNSZWN0LmhlaWdodCAtIHRoaXMubWluaW1hcFNpemUuaGVpZ2h0KSAvIDJcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVWaWV3cG9pbnQoKTogdm9pZCB7XG4gICAgLy8gVXBkYXRlIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgdmlld3BvaW50IHJlY3RhbmdsZS5cbiAgICBzZWxlY3QodGhpcy52aWV3cG9pbnQpLmF0dHIoJ3gnLCB0aGlzLnZpZXdwb2ludENvb3JkLngpLmF0dHIoJ3knLCB0aGlzLnZpZXdwb2ludENvb3JkLnkpO1xuICAgIC8vIFVwZGF0ZSB0aGUgdHJhbnNsYXRpb24gdmVjdG9yIG9mIHRoZSBtYWluIHN2ZyB0byByZWZsZWN0IHRoZVxuICAgIC8vIG5ldyB2aWV3cG9pbnQuXG4gICAgY29uc3QgbWFpblggPSAoLXRoaXMudmlld3BvaW50Q29vcmQueCAqIHRoaXMuc2NhbGVNYWluKSAvIHRoaXMuc2NhbGVNaW5pbWFwO1xuICAgIGNvbnN0IG1haW5ZID0gKC10aGlzLnZpZXdwb2ludENvb3JkLnkgKiB0aGlzLnNjYWxlTWFpbikgLyB0aGlzLnNjYWxlTWluaW1hcDtcbiAgICBzZWxlY3QodGhpcy5zdmcpLmNhbGwodGhpcy5tYWluWm9vbS50cmFuc2Zvcm0sIHpvb21JZGVudGl0eS50cmFuc2xhdGUobWFpblgsIG1haW5ZKS5zY2FsZSh0aGlzLnNjYWxlTWFpbikpO1xuICB9XG5cbiAgdXBkYXRlKCk6IHZvaWQge1xuICAgIGxldCBzY2VuZVNpemUgPSBudWxsO1xuICAgIHRyeSB7XG4gICAgICAvLyBHZXQgdGhlIHNpemUgb2YgdGhlIGVudGlyZSBzY2VuZS5cbiAgICAgIHNjZW5lU2l6ZSA9IHRoaXMuem9vbUcuZ2V0QkJveCgpO1xuICAgICAgaWYgKHNjZW5lU2l6ZS53aWR0aCA9PT0gMCkge1xuICAgICAgICAvLyBUaGVyZSBpcyBubyBzY2VuZSBhbnltb3JlLiBXZSBoYXZlIGJlZW4gZGV0YWNoZWQgZnJvbSB0aGUgZG9tLlxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gRmlyZWZveCBwcm9kdWNlZCBOU19FUlJPUl9GQUlMVVJFIGlmIHdlIGhhdmUgYmVlblxuICAgICAgLy8gZGV0YWNoZWQgZnJvbSB0aGUgZG9tLlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHN2Z1NlbGVjdGlvbiA9IHNlbGVjdCh0aGlzLnN2Zyk7XG4gICAgLy8gUmVhZCBhbGwgdGhlIHN0eWxlIHJ1bGVzIGluIHRoZSBkb2N1bWVudCBhbmQgZW1iZWQgdGhlbSBpbnRvIHRoZSBzdmcuXG4gICAgLy8gVGhlIHN2ZyBuZWVkcyB0byBiZSBzZWxmIGNvbnRhaW5lZCwgaS5lLiBhbGwgdGhlIHN0eWxlIHJ1bGVzIG5lZWQgdG8gYmVcbiAgICAvLyBlbWJlZGRlZCBzbyB0aGUgY2FudmFzIG91dHB1dCBtYXRjaGVzIHRoZSBvcmlnaW4uXG4gICAgbGV0IHN0eWxlc1RleHQgPSAnJztcblxuICAgIGZvciAoY29uc3QgayBvZiBuZXcgQXJyYXkoZG9jdW1lbnQuc3R5bGVTaGVldHMubGVuZ3RoKS5rZXlzKCkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGNzc1J1bGVzID1cbiAgICAgICAgICAoZG9jdW1lbnQuc3R5bGVTaGVldHNba10gYXMgTnpTYWZlQW55KS5jc3NSdWxlcyB8fCAoZG9jdW1lbnQuc3R5bGVTaGVldHNba10gYXMgTnpTYWZlQW55KS5ydWxlcztcbiAgICAgICAgaWYgKGNzc1J1bGVzID09IG51bGwpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IGkgb2YgbmV3IEFycmF5KGNzc1J1bGVzLmxlbmd0aCkua2V5cygpKSB7XG4gICAgICAgICAgLy8gUmVtb3ZlIHRmLSogc2VsZWN0b3JzIGZyb20gdGhlIHN0eWxlcy5cbiAgICAgICAgICBzdHlsZXNUZXh0ICs9IGAke2Nzc1J1bGVzW2ldLmNzc1RleHQucmVwbGFjZSgvID90Zi1bXFx3LV0rID8vZywgJycpfVxcbmA7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGU6IE56U2FmZUFueSkge1xuICAgICAgICBpZiAoZS5uYW1lICE9PSAnU2VjdXJpdHlFcnJvcicpIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGVtcG9yYXJpbHkgYWRkIHRoZSBjc3MgcnVsZXMgdG8gdGhlIG1haW4gc3ZnLlxuICAgIGNvbnN0IHN2Z1N0eWxlID0gc3ZnU2VsZWN0aW9uLmFwcGVuZCgnc3R5bGUnKTtcbiAgICBzdmdTdHlsZS50ZXh0KHN0eWxlc1RleHQpO1xuXG4gICAgLy8gVGVtcG9yYXJpbHkgcmVtb3ZlIHRoZSB6b29tL3BhbiB0cmFuc2Zvcm0gZnJvbSB0aGUgbWFpbiBzdmcgc2luY2Ugd2VcbiAgICAvLyB3YW50IHRoZSBtaW5pbWFwIHRvIHNob3cgYSB6b29tZWQtb3V0IGFuZCBjZW50ZXJlZCB2aWV3LlxuICAgIGNvbnN0IHpvb21HU2VsZWN0aW9uID0gc2VsZWN0KHRoaXMuem9vbUcpO1xuICAgIGNvbnN0IHpvb21UcmFuc2Zvcm0gPSB6b29tR1NlbGVjdGlvbi5hdHRyKCd0cmFuc2Zvcm0nKTtcbiAgICB6b29tR1NlbGVjdGlvbi5hdHRyKCd0cmFuc2Zvcm0nLCBudWxsKTtcblxuICAgIC8vIFNpbmNlIHdlIGFkZCBwYWRkaW5nLCBhY2NvdW50IGZvciB0aGF0IGhlcmUuXG4gICAgc2NlbmVTaXplLmhlaWdodCArPSB0aGlzLmxhYmVsUGFkZGluZyAqIDI7XG4gICAgc2NlbmVTaXplLndpZHRoICs9IHRoaXMubGFiZWxQYWRkaW5nICogMjtcblxuICAgIC8vIFRlbXBvcmFyaWx5IGFzc2lnbiBhbiBleHBsaWNpdCB3aWR0aC9oZWlnaHQgdG8gdGhlIG1haW4gc3ZnLCBzaW5jZVxuICAgIC8vIGl0IGRvZXNuJ3QgaGF2ZSBvbmUgKHVzZXMgZmxleC1ib3gpLCBidXQgd2UgbmVlZCBpdCBmb3IgdGhlIGNhbnZhc1xuICAgIC8vIHRvIHdvcmsuXG4gICAgc3ZnU2VsZWN0aW9uLmF0dHIoJ3dpZHRoJywgc2NlbmVTaXplLndpZHRoKS5hdHRyKCdoZWlnaHQnLCBzY2VuZVNpemUuaGVpZ2h0KTtcblxuICAgIC8vIFNpbmNlIHRoZSBjb250ZW50IGluc2lkZSB0aGUgc3ZnIGNoYW5nZWQgKGUuZy4gYSBub2RlIHdhcyBleHBhbmRlZCksXG4gICAgLy8gdGhlIGFzcGVjdCByYXRpbyBoYXZlIGFsc28gY2hhbmdlZC4gVGh1cywgd2UgbmVlZCB0byB1cGRhdGUgdGhlIHNjYWxlXG4gICAgLy8gZmFjdG9yIG9mIHRoZSBtaW5pbWFwLiBUaGUgc2NhbGUgZmFjdG9yIGlzIGRldGVybWluZWQgc3VjaCB0aGF0IGJvdGhcbiAgICAvLyB0aGUgd2lkdGggYW5kIGhlaWdodCBvZiB0aGUgbWluaW1hcCBhcmUgPD0gbWF4aW11bSBzcGVjaWZpZWQgdy9oLlxuICAgIHRoaXMuc2NhbGVNaW5pbWFwID0gdGhpcy5tYXhXaWR0aCAvIE1hdGgubWF4KHNjZW5lU2l6ZS53aWR0aCwgc2NlbmVTaXplLmhlaWdodCk7XG4gICAgdGhpcy5taW5pbWFwU2l6ZSA9IHtcbiAgICAgIHdpZHRoOiBzY2VuZVNpemUud2lkdGggKiB0aGlzLnNjYWxlTWluaW1hcCxcbiAgICAgIGhlaWdodDogc2NlbmVTaXplLmhlaWdodCAqIHRoaXMuc2NhbGVNaW5pbWFwXG4gICAgfTtcblxuICAgIGNvbnN0IG1pbmltYXBPZmZzZXQgPSB0aGlzLm1pbmltYXBPZmZzZXQoKTtcblxuICAgIC8vIFVwZGF0ZSB0aGUgc2l6ZSBvZiB0aGUgbWluaW1hcCdzIHN2ZywgdGhlIGJ1ZmZlciBjYW52YXMgYW5kIHRoZVxuICAgIC8vIHZpZXdwb2ludCByZWN0LlxuICAgIHNlbGVjdCh0aGlzLm1pbmltYXBTdmcpLmF0dHIodGhpcy5taW5pbWFwU2l6ZSBhcyBOelNhZmVBbnkpO1xuICAgIHNlbGVjdCh0aGlzLmNhbnZhc0J1ZmZlcikuYXR0cih0aGlzLm1pbmltYXBTaXplIGFzIE56U2FmZUFueSk7XG5cbiAgICBpZiAodGhpcy50cmFuc2xhdGUgIT0gbnVsbCAmJiB0aGlzLnpvb20gIT0gbnVsbCkge1xuICAgICAgLy8gVXBkYXRlIHRoZSB2aWV3cG9pbnQgcmVjdGFuZ2xlIHNoYXBlIHNpbmNlIHRoZSBhc3BlY3QgcmF0aW8gb2YgdGhlXG4gICAgICAvLyBtYXAgaGFzIGNoYW5nZWQuXG4gICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiByZXFBbmltRnJhbWUoKCkgPT4gdGhpcy56b29tKCkpKTtcbiAgICB9XG5cbiAgICAvLyBTZXJpYWxpemUgdGhlIG1haW4gc3ZnIHRvIGEgc3RyaW5nIHdoaWNoIHdpbGwgYmUgdXNlZCBhcyB0aGUgcmVuZGVyaW5nXG4gICAgLy8gY29udGVudCBmb3IgdGhlIGNhbnZhcy5cbiAgICBjb25zdCBzdmdYbWwgPSBuZXcgWE1MU2VyaWFsaXplcigpLnNlcmlhbGl6ZVRvU3RyaW5nKHRoaXMuc3ZnKTtcblxuICAgIC8vIE5vdyB0aGF0IHRoZSBzdmcgaXMgc2VyaWFsaXplZCBmb3IgcmVuZGVyaW5nLCByZW1vdmUgdGhlIHRlbXBvcmFyaWx5XG4gICAgLy8gYXNzaWduZWQgc3R5bGVzLCBleHBsaWNpdCB3aWR0aCBhbmQgaGVpZ2h0IGFuZCBicmluZyBiYWNrIHRoZSBwYW4vem9vbVxuICAgIC8vIHRyYW5zZm9ybS5cbiAgICBzdmdTdHlsZS5yZW1vdmUoKTtcbiAgICBzdmdTZWxlY3Rpb24uYXR0cignd2lkdGgnLCAnMTAwJScpLmF0dHIoJ2hlaWdodCcsICcxMDAlJyk7XG5cbiAgICB6b29tR1NlbGVjdGlvbi5hdHRyKCd0cmFuc2Zvcm0nLCB6b29tVHJhbnNmb3JtKTtcblxuICAgIGNvbnN0IGltYWdlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7XG4gICAgY29uc3Qgb25Mb2FkID0gKCk6IHZvaWQgPT4ge1xuICAgICAgLy8gRHJhdyB0aGUgc3ZnIGNvbnRlbnQgb250byB0aGUgYnVmZmVyIGNhbnZhcy5cbiAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmNhbnZhc0J1ZmZlci5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgY29udGV4dCEuY2xlYXJSZWN0KDAsIDAsIHRoaXMuY2FudmFzQnVmZmVyLndpZHRoLCB0aGlzLmNhbnZhc0J1ZmZlci5oZWlnaHQpO1xuXG4gICAgICBjb250ZXh0IS5kcmF3SW1hZ2UoaW1hZ2UsIG1pbmltYXBPZmZzZXQueCwgbWluaW1hcE9mZnNldC55LCB0aGlzLm1pbmltYXBTaXplLndpZHRoLCB0aGlzLm1pbmltYXBTaXplLmhlaWdodCk7XG5cbiAgICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgcmVxQW5pbUZyYW1lKCgpID0+IHtcbiAgICAgICAgICAvLyBIaWRlIHRoZSBvbGQgY2FudmFzIGFuZCBzaG93IHRoZSBuZXcgYnVmZmVyIGNhbnZhcy5cbiAgICAgICAgICBzZWxlY3QodGhpcy5jYW52YXNCdWZmZXIpLnN0eWxlKCdkaXNwbGF5JywgJ2Jsb2NrJyk7XG4gICAgICAgICAgc2VsZWN0KHRoaXMuY2FudmFzKS5zdHlsZSgnZGlzcGxheScsICdub25lJyk7XG4gICAgICAgICAgLy8gU3dhcCB0aGUgdHdvIGNhbnZhc2VzLlxuICAgICAgICAgIFt0aGlzLmNhbnZhcywgdGhpcy5jYW52YXNCdWZmZXJdID0gW3RoaXMuY2FudmFzQnVmZmVyLCB0aGlzLmNhbnZhc107XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIGltYWdlLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBvbkxvYWQpO1xuICAgIGltYWdlLnNyYyA9IGBkYXRhOmltYWdlL3N2Zyt4bWw7Y2hhcnNldD11dGYtOCwke2VuY29kZVVSSUNvbXBvbmVudChzdmdYbWwpfWA7XG5cbiAgICB0aGlzLnVubGlzdGVuZXJzLnB1c2goKCkgPT4ge1xuICAgICAgaW1hZ2UucmVtb3ZlRXZlbnRMaXN0ZW5lcignbG9hZCcsIG9uTG9hZCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyBjaGFuZ2VzIGluIHpvb21pbmcvcGFubmluZy4gU2hvdWxkIGJlIGNhbGxlZCBmcm9tIHRoZSBtYWluIHN2Z1xuICAgKiB0byBub3RpZnkgdGhhdCBhIHpvb20vcGFuIHdhcyBwZXJmb3JtZWQgYW5kIHRoaXMgbWluaW1hcCB3aWxsIHVwZGF0ZSBpdCdzXG4gICAqIHZpZXdwb2ludCByZWN0YW5nbGUuXG4gICAqXG4gICAqIEBwYXJhbSB0cmFuc2Zvcm1cbiAgICovXG4gIHpvb20odHJhbnNmb3JtPzogWm9vbVRyYW5zZm9ybSB8IE56Wm9vbVRyYW5zZm9ybSk6IHZvaWQge1xuICAgIGlmICh0aGlzLnNjYWxlTWluaW1hcCA9PSBudWxsKSB7XG4gICAgICAvLyBTY2VuZSBpcyBub3QgcmVhZHkgeWV0LlxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBVcGRhdGUgdGhlIG5ldyB0cmFuc2xhdGUgYW5kIHNjYWxlIHBhcmFtcywgb25seSBpZiBzcGVjaWZpZWQuXG4gICAgaWYgKHRyYW5zZm9ybSkge1xuICAgICAgdGhpcy50cmFuc2xhdGUgPSBbdHJhbnNmb3JtLngsIHRyYW5zZm9ybS55XTtcbiAgICAgIHRoaXMuc2NhbGVNYWluID0gdHJhbnNmb3JtLms7XG4gICAgfVxuXG4gICAgLy8gVXBkYXRlIHRoZSBsb2NhdGlvbiBvZiB0aGUgdmlld3BvaW50IHJlY3RhbmdsZS5cbiAgICBjb25zdCBzdmdSZWN0ID0gdGhpcy5zdmcuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgbWluaW1hcE9mZnNldCA9IHRoaXMubWluaW1hcE9mZnNldCgpO1xuICAgIGNvbnN0IHZpZXdwb2ludFNlbGVjdGlvbiA9IHNlbGVjdCh0aGlzLnZpZXdwb2ludCk7XG4gICAgdGhpcy52aWV3cG9pbnRDb29yZC54ID0gKC10aGlzLnRyYW5zbGF0ZVswXSAqIHRoaXMuc2NhbGVNaW5pbWFwKSAvIHRoaXMuc2NhbGVNYWluO1xuICAgIHRoaXMudmlld3BvaW50Q29vcmQueSA9ICgtdGhpcy50cmFuc2xhdGVbMV0gKiB0aGlzLnNjYWxlTWluaW1hcCkgLyB0aGlzLnNjYWxlTWFpbjtcbiAgICBjb25zdCB2aWV3cG9pbnRXaWR0aCA9IChzdmdSZWN0LndpZHRoICogdGhpcy5zY2FsZU1pbmltYXApIC8gdGhpcy5zY2FsZU1haW47XG4gICAgY29uc3Qgdmlld3BvaW50SGVpZ2h0ID0gKHN2Z1JlY3QuaGVpZ2h0ICogdGhpcy5zY2FsZU1pbmltYXApIC8gdGhpcy5zY2FsZU1haW47XG4gICAgdmlld3BvaW50U2VsZWN0aW9uXG4gICAgICAuYXR0cigneCcsIHRoaXMudmlld3BvaW50Q29vcmQueCArIG1pbmltYXBPZmZzZXQueClcbiAgICAgIC5hdHRyKCd5JywgdGhpcy52aWV3cG9pbnRDb29yZC55ICsgbWluaW1hcE9mZnNldC55KVxuICAgICAgLmF0dHIoJ3dpZHRoJywgdmlld3BvaW50V2lkdGgpXG4gICAgICAuYXR0cignaGVpZ2h0Jywgdmlld3BvaW50SGVpZ2h0KTtcbiAgICAvLyBTaG93L2hpZGUgdGhlIG1pbmltYXAgZGVwZW5kaW5nIG9uIHRoZSB2aWV3cG9pbnQgYXJlYSBhcyBmcmFjdGlvbiBvZiB0aGVcbiAgICAvLyB3aG9sZSBtaW5pbWFwLlxuICAgIGNvbnN0IG1hcFdpZHRoID0gdGhpcy5taW5pbWFwU2l6ZS53aWR0aDtcbiAgICBjb25zdCBtYXBIZWlnaHQgPSB0aGlzLm1pbmltYXBTaXplLmhlaWdodDtcbiAgICBjb25zdCB4ID0gdGhpcy52aWV3cG9pbnRDb29yZC54O1xuICAgIGNvbnN0IHkgPSB0aGlzLnZpZXdwb2ludENvb3JkLnk7XG4gICAgY29uc3QgdyA9IE1hdGgubWluKE1hdGgubWF4KDAsIHggKyB2aWV3cG9pbnRXaWR0aCksIG1hcFdpZHRoKSAtIE1hdGgubWluKE1hdGgubWF4KDAsIHgpLCBtYXBXaWR0aCk7XG4gICAgY29uc3QgaCA9IE1hdGgubWluKE1hdGgubWF4KDAsIHkgKyB2aWV3cG9pbnRIZWlnaHQpLCBtYXBIZWlnaHQpIC0gTWF0aC5taW4oTWF0aC5tYXgoMCwgeSksIG1hcEhlaWdodCk7XG4gICAgY29uc3QgZnJhY0ludGVyc2VjdCA9ICh3ICogaCkgLyAobWFwV2lkdGggKiBtYXBIZWlnaHQpO1xuICAgIGlmIChmcmFjSW50ZXJzZWN0IDwgRlJBQ19WSUVXUE9JTlRfQVJFQSkge1xuICAgICAgdGhpcy5taW5pbWFwLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1pbmltYXAuY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7XG4gICAgfVxuICB9XG59XG4iXX0=