UNPKG

ng-zorro-antd

Version:

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

204 lines 34.9 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 = new Image(); 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWluaW1hcC5qcyIsInNvdXJjZVJvb3QiOiIvaG9tZS92c3RzL3dvcmsvMS9zL2NvbXBvbmVudHMvZ3JhcGgvIiwic291cmNlcyI6WyJjb3JlL21pbmltYXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUMvQixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUMvQyxPQUFPLEVBQWdCLFlBQVksRUFBaUIsTUFBTSxTQUFTLENBQUM7QUFJcEUsTUFBTSxtQkFBbUIsR0FBRyxHQUFHLENBQUM7QUFFaEMsTUFBTSxPQUFPLE9BQU87SUFtQmxCLFlBQ0UsR0FBa0IsRUFDbEIsS0FBa0IsRUFDbEIsUUFBNEMsRUFDNUMsT0FBb0IsRUFDcEIsUUFBZ0IsRUFDaEIsWUFBb0I7UUFFcEIsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZixJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztRQUNqQyxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdkMsTUFBTSxpQkFBaUIsR0FBRyxjQUFjLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sZ0JBQWdCLEdBQUcsaUJBQWlCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxNQUFNLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLElBQUksRUFBdUIsQ0FBQztRQUNuRixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMscUJBQXFCLEVBQUUsQ0FB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RyxTQUFTLENBQUMsQ0FBQztRQUN2RCxJQUFJLGFBQWEsR0FBRyxtQkFBbUIsRUFBRTtZQUN2QyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDekM7YUFBTTtZQUNMLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUN0QztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9naXRodWIuY29tL05HLVpPUlJPL25nLXpvcnJvLWFudGQvYmxvYi9tYXN0ZXIvTElDRU5TRVxuICovXG5cbmltcG9ydCB7IGRyYWcgfSBmcm9tICdkMy1kcmFnJztcbmltcG9ydCB7IHBvaW50ZXIsIHNlbGVjdCB9IGZyb20gJ2QzLXNlbGVjdGlvbic7XG5pbXBvcnQgeyBab29tQmVoYXZpb3IsIHpvb21JZGVudGl0eSwgWm9vbVRyYW5zZm9ybSB9IGZyb20gJ2QzLXpvb20nO1xuaW1wb3J0IHsgTnpTYWZlQW55IH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL3R5cGVzJztcbmltcG9ydCB7IE56Wm9vbVRyYW5zZm9ybSB9IGZyb20gJy4uL2ludGVyZmFjZSc7XG5cbmNvbnN0IEZSQUNfVklFV1BPSU5UX0FSRUEgPSAwLjg7XG5cbmV4cG9ydCBjbGFzcyBNaW5pbWFwIHtcbiAgcHJpdmF0ZSBtaW5pbWFwOiBIVE1MRWxlbWVudDtcbiAgcHJpdmF0ZSBjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50O1xuICBwcml2YXRlIGNhbnZhc1JlY3Q6IENsaWVudFJlY3Q7XG4gIHByaXZhdGUgY2FudmFzQnVmZmVyOiBIVE1MQ2FudmFzRWxlbWVudDtcbiAgcHJpdmF0ZSBtaW5pbWFwU3ZnOiBTVkdTVkdFbGVtZW50O1xuICBwcml2YXRlIHZpZXdwb2ludDogU1ZHUmVjdEVsZW1lbnQ7XG4gIHByaXZhdGUgc2NhbGVNaW5pbWFwITogbnVtYmVyO1xuICBwcml2YXRlIHNjYWxlTWFpbiE6IG51bWJlcjtcbiAgcHJpdmF0ZSBtYXhXaWR0aDogbnVtYmVyO1xuICBwcml2YXRlIHRyYW5zbGF0ZSE6IFtudW1iZXIsIG51bWJlcl07XG4gIHByaXZhdGUgdmlld3BvaW50Q29vcmQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfTtcbiAgcHJpdmF0ZSBtaW5pbWFwU2l6ZSE6IHsgd2lkdGg6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfTtcbiAgcHJpdmF0ZSBsYWJlbFBhZGRpbmc6IG51bWJlcjtcblxuICBwcml2YXRlIHN2ZzogU1ZHU1ZHRWxlbWVudDtcbiAgcHJpdmF0ZSB6b29tRzogU1ZHR0VsZW1lbnQ7XG4gIHByaXZhdGUgbWFpblpvb206IFpvb21CZWhhdmlvcjxOelNhZmVBbnksIE56U2FmZUFueT47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc3ZnOiBTVkdTVkdFbGVtZW50LFxuICAgIHpvb21HOiBTVkdHRWxlbWVudCxcbiAgICBtYWluWm9vbTogWm9vbUJlaGF2aW9yPE56U2FmZUFueSwgTnpTYWZlQW55PixcbiAgICBtaW5pbWFwOiBIVE1MRWxlbWVudCxcbiAgICBtYXhXaWR0aDogbnVtYmVyLFxuICAgIGxhYmVsUGFkZGluZzogbnVtYmVyXG4gICkge1xuICAgIHRoaXMuc3ZnID0gc3ZnO1xuICAgIHRoaXMubGFiZWxQYWRkaW5nID0gbGFiZWxQYWRkaW5nO1xuICAgIHRoaXMuem9vbUcgPSB6b29tRztcbiAgICB0aGlzLm1haW5ab29tID0gbWFpblpvb207XG4gICAgdGhpcy5tYXhXaWR0aCA9IG1heFdpZHRoO1xuICAgIGNvbnN0IG1pbmltYXBFbGVtZW50ID0gc2VsZWN0KG1pbmltYXApO1xuICAgIGNvbnN0IG1pbmltYXBTdmdFbGVtZW50ID0gbWluaW1hcEVsZW1lbnQuc2VsZWN0KCdzdmcnKTtcbiAgICBjb25zdCB2aWV3cG9pbnRFbGVtZW50ID0gbWluaW1hcFN2Z0VsZW1lbnQuc2VsZWN0KCdyZWN0Jyk7XG4gICAgdGhpcy5jYW52YXMgPSBtaW5pbWFwRWxlbWVudC5zZWxlY3QoJ2NhbnZhcy52aWV3cG9ydCcpLm5vZGUoKSBhcyBIVE1MQ2FudmFzRWxlbWVudDtcbiAgICB0aGlzLmNhbnZhc1JlY3QgPSB0aGlzLmNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIGNvbnN0IGhhbmRsZUV2ZW50ID0gKGV2ZW50OiBOelNhZmVBbnkpOiB2b2lkID0+IHtcbiAgICAgIGNvbnN0IG1pbmltYXBPZmZzZXQgPSB0aGlzLm1pbmltYXBPZmZzZXQoKTtcbiAgICAgIGNvbnN0IHdpZHRoID0gTnVtYmVyKHZpZXdwb2ludEVsZW1lbnQuYXR0cignd2lkdGgnKSk7XG4gICAgICBjb25zdCBoZWlnaHQgPSBOdW1iZXIodmlld3BvaW50RWxlbWVudC5hdHRyKCdoZWlnaHQnKSk7XG4gICAgICBjb25zdCBjbGlja0Nvb3JkcyA9IHBvaW50ZXIoZXZlbnQsIG1pbmltYXBTdmdFbGVtZW50Lm5vZGUoKSBhcyBOelNhZmVBbnkpO1xuICAgICAgdGhpcy52aWV3cG9pbnRDb29yZC54ID0gY2xpY2tDb29yZHNbMF0gLSB3aWR0aCAvIDIgLSBtaW5pbWFwT2Zmc2V0Lng7XG4gICAgICB0aGlzLnZpZXdwb2ludENvb3JkLnkgPSBjbGlja0Nvb3Jkc1sxXSAtIGhlaWdodCAvIDIgLSBtaW5pbWFwT2Zmc2V0Lnk7XG4gICAgICB0aGlzLnVwZGF0ZVZpZXdwb2ludCgpO1xuICAgIH07XG4gICAgdGhpcy52aWV3cG9pbnRDb29yZCA9IHsgeDogMCwgeTogMCB9O1xuICAgIGNvbnN0IGRyYWdFdmVudCA9IGRyYWcoKS5zdWJqZWN0KE9iamVjdCkub24oJ2RyYWcnLCBoYW5kbGVFdmVudCk7XG4gICAgdmlld3BvaW50RWxlbWVudC5kYXR1bSh0aGlzLnZpZXdwb2ludENvb3JkIGFzIE56U2FmZUFueSkuY2FsbChkcmFnRXZlbnQgYXMgTnpTYWZlQW55KTtcblxuICAgIC8vIE1ha2UgdGhlIG1pbmltYXAgY2xpY2thYmxlLlxuICAgIG1pbmltYXBTdmdFbGVtZW50Lm9uKCdjbGljaycsIGV2ZW50ID0+IHtcbiAgICAgIGlmICgoZXZlbnQgYXMgRXZlbnQpLmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgLy8gVGhpcyBjbGljayB3YXMgcGFydCBvZiBhIGRyYWcgZXZlbnQsIHNvIHN1cHByZXNzIGl0LlxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBoYW5kbGVFdmVudChldmVudCk7XG4gICAgfSk7XG4gICAgdGhpcy52aWV3cG9pbnQgPSB2aWV3cG9pbnRFbGVtZW50Lm5vZGUoKSBhcyBTVkdSZWN0RWxlbWVudDtcbiAgICB0aGlzLm1pbmltYXBTdmcgPSBtaW5pbWFwU3ZnRWxlbWVudC5ub2RlKCkgYXMgU1ZHU1ZHRWxlbWVudDtcbiAgICB0aGlzLm1pbmltYXAgPSBtaW5pbWFwO1xuICAgIHRoaXMuY2FudmFzQnVmZmVyID0gbWluaW1hcEVsZW1lbnQuc2VsZWN0KCdjYW52YXMuYnVmZmVyJykubm9kZSgpIGFzIEhUTUxDYW52YXNFbGVtZW50O1xuICAgIHRoaXMudXBkYXRlKCk7XG4gIH1cblxuICBwcml2YXRlIG1pbmltYXBPZmZzZXQoKTogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHtcbiAgICByZXR1cm4ge1xuICAgICAgeDogKHRoaXMuY2FudmFzUmVjdC53aWR0aCAtIHRoaXMubWluaW1hcFNpemUud2lkdGgpIC8gMixcbiAgICAgIHk6ICh0aGlzLmNhbnZhc1JlY3QuaGVpZ2h0IC0gdGhpcy5taW5pbWFwU2l6ZS5oZWlnaHQpIC8gMlxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVZpZXdwb2ludCgpOiB2b2lkIHtcbiAgICAvLyBVcGRhdGUgdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSB2aWV3cG9pbnQgcmVjdGFuZ2xlLlxuICAgIHNlbGVjdCh0aGlzLnZpZXdwb2ludCkuYXR0cigneCcsIHRoaXMudmlld3BvaW50Q29vcmQueCkuYXR0cigneScsIHRoaXMudmlld3BvaW50Q29vcmQueSk7XG4gICAgLy8gVXBkYXRlIHRoZSB0cmFuc2xhdGlvbiB2ZWN0b3Igb2YgdGhlIG1haW4gc3ZnIHRvIHJlZmxlY3QgdGhlXG4gICAgLy8gbmV3IHZpZXdwb2ludC5cbiAgICBjb25zdCBtYWluWCA9ICgtdGhpcy52aWV3cG9pbnRDb29yZC54ICogdGhpcy5zY2FsZU1haW4pIC8gdGhpcy5zY2FsZU1pbmltYXA7XG4gICAgY29uc3QgbWFpblkgPSAoLXRoaXMudmlld3BvaW50Q29vcmQueSAqIHRoaXMuc2NhbGVNYWluKSAvIHRoaXMuc2NhbGVNaW5pbWFwO1xuICAgIHNlbGVjdCh0aGlzLnN2ZykuY2FsbCh0aGlzLm1haW5ab29tLnRyYW5zZm9ybSwgem9vbUlkZW50aXR5LnRyYW5zbGF0ZShtYWluWCwgbWFpblkpLnNjYWxlKHRoaXMuc2NhbGVNYWluKSk7XG4gIH1cblxuICB1cGRhdGUoKTogdm9pZCB7XG4gICAgbGV0IHNjZW5lU2l6ZSA9IG51bGw7XG4gICAgdHJ5IHtcbiAgICAgIC8vIEdldCB0aGUgc2l6ZSBvZiB0aGUgZW50aXJlIHNjZW5lLlxuICAgICAgc2NlbmVTaXplID0gdGhpcy56b29tRy5nZXRCQm94KCk7XG4gICAgICBpZiAoc2NlbmVTaXplLndpZHRoID09PSAwKSB7XG4gICAgICAgIC8vIFRoZXJlIGlzIG5vIHNjZW5lIGFueW1vcmUuIFdlIGhhdmUgYmVlbiBkZXRhY2hlZCBmcm9tIHRoZSBkb20uXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBGaXJlZm94IHByb2R1Y2VkIE5TX0VSUk9SX0ZBSUxVUkUgaWYgd2UgaGF2ZSBiZWVuXG4gICAgICAvLyBkZXRhY2hlZCBmcm9tIHRoZSBkb20uXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc3ZnU2VsZWN0aW9uID0gc2VsZWN0KHRoaXMuc3ZnKTtcbiAgICAvLyBSZWFkIGFsbCB0aGUgc3R5bGUgcnVsZXMgaW4gdGhlIGRvY3VtZW50IGFuZCBlbWJlZCB0aGVtIGludG8gdGhlIHN2Zy5cbiAgICAvLyBUaGUgc3ZnIG5lZWRzIHRvIGJlIHNlbGYgY29udGFpbmVkLCBpLmUuIGFsbCB0aGUgc3R5bGUgcnVsZXMgbmVlZCB0byBiZVxuICAgIC8vIGVtYmVkZGVkIHNvIHRoZSBjYW52YXMgb3V0cHV0IG1hdGNoZXMgdGhlIG9yaWdpbi5cbiAgICBsZXQgc3R5bGVzVGV4dCA9ICcnO1xuXG4gICAgZm9yIChjb25zdCBrIG9mIG5ldyBBcnJheShkb2N1bWVudC5zdHlsZVNoZWV0cy5sZW5ndGgpLmtleXMoKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY3NzUnVsZXMgPSAoZG9jdW1lbnQuc3R5bGVTaGVldHNba10gYXMgTnpTYWZlQW55KS5jc3NSdWxlcyB8fCAoZG9jdW1lbnQuc3R5bGVTaGVldHNba10gYXMgTnpTYWZlQW55KS5ydWxlcztcbiAgICAgICAgaWYgKGNzc1J1bGVzID09IG51bGwpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IGkgb2YgbmV3IEFycmF5KGNzc1J1bGVzLmxlbmd0aCkua2V5cygpKSB7XG4gICAgICAgICAgLy8gUmVtb3ZlIHRmLSogc2VsZWN0b3JzIGZyb20gdGhlIHN0eWxlcy5cbiAgICAgICAgICBzdHlsZXNUZXh0ICs9IGNzc1J1bGVzW2ldLmNzc1RleHQucmVwbGFjZSgvID90Zi1bXFx3LV0rID8vZywgJycpICsgJ1xcbic7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUubmFtZSAhPT0gJ1NlY3VyaXR5RXJyb3InKSB7XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRlbXBvcmFyaWx5IGFkZCB0aGUgY3NzIHJ1bGVzIHRvIHRoZSBtYWluIHN2Zy5cbiAgICBjb25zdCBzdmdTdHlsZSA9IHN2Z1NlbGVjdGlvbi5hcHBlbmQoJ3N0eWxlJyk7XG4gICAgc3ZnU3R5bGUudGV4dChzdHlsZXNUZXh0KTtcblxuICAgIC8vIFRlbXBvcmFyaWx5IHJlbW92ZSB0aGUgem9vbS9wYW4gdHJhbnNmb3JtIGZyb20gdGhlIG1haW4gc3ZnIHNpbmNlIHdlXG4gICAgLy8gd2FudCB0aGUgbWluaW1hcCB0byBzaG93IGEgem9vbWVkLW91dCBhbmQgY2VudGVyZWQgdmlldy5cbiAgICBjb25zdCB6b29tR1NlbGVjdGlvbiA9IHNlbGVjdCh0aGlzLnpvb21HKTtcbiAgICBjb25zdCB6b29tVHJhbnNmb3JtID0gem9vbUdTZWxlY3Rpb24uYXR0cigndHJhbnNmb3JtJyk7XG4gICAgem9vbUdTZWxlY3Rpb24uYXR0cigndHJhbnNmb3JtJywgbnVsbCk7XG5cbiAgICAvLyBTaW5jZSB3ZSBhZGQgcGFkZGluZywgYWNjb3VudCBmb3IgdGhhdCBoZXJlLlxuICAgIHNjZW5lU2l6ZS5oZWlnaHQgKz0gdGhpcy5sYWJlbFBhZGRpbmcgKiAyO1xuICAgIHNjZW5lU2l6ZS53aWR0aCArPSB0aGlzLmxhYmVsUGFkZGluZyAqIDI7XG5cbiAgICAvLyBUZW1wb3JhcmlseSBhc3NpZ24gYW4gZXhwbGljaXQgd2lkdGgvaGVpZ2h0IHRvIHRoZSBtYWluIHN2Zywgc2luY2VcbiAgICAvLyBpdCBkb2Vzbid0IGhhdmUgb25lICh1c2VzIGZsZXgtYm94KSwgYnV0IHdlIG5lZWQgaXQgZm9yIHRoZSBjYW52YXNcbiAgICAvLyB0byB3b3JrLlxuICAgIHN2Z1NlbGVjdGlvbi5hdHRyKCd3aWR0aCcsIHNjZW5lU2l6ZS53aWR0aCkuYXR0cignaGVpZ2h0Jywgc2NlbmVTaXplLmhlaWdodCk7XG5cbiAgICAvLyBTaW5jZSB0aGUgY29udGVudCBpbnNpZGUgdGhlIHN2ZyBjaGFuZ2VkIChlLmcuIGEgbm9kZSB3YXMgZXhwYW5kZWQpLFxuICAgIC8vIHRoZSBhc3BlY3QgcmF0aW8gaGF2ZSBhbHNvIGNoYW5nZWQuIFRodXMsIHdlIG5lZWQgdG8gdXBkYXRlIHRoZSBzY2FsZVxuICAgIC8vIGZhY3RvciBvZiB0aGUgbWluaW1hcC4gVGhlIHNjYWxlIGZhY3RvciBpcyBkZXRlcm1pbmVkIHN1Y2ggdGhhdCBib3RoXG4gICAgLy8gdGhlIHdpZHRoIGFuZCBoZWlnaHQgb2YgdGhlIG1pbmltYXAgYXJlIDw9IG1heGltdW0gc3BlY2lmaWVkIHcvaC5cbiAgICB0aGlzLnNjYWxlTWluaW1hcCA9IHRoaXMubWF4V2lkdGggLyBNYXRoLm1heChzY2VuZVNpemUud2lkdGgsIHNjZW5lU2l6ZS5oZWlnaHQpO1xuICAgIHRoaXMubWluaW1hcFNpemUgPSB7XG4gICAgICB3aWR0aDogc2NlbmVTaXplLndpZHRoICogdGhpcy5zY2FsZU1pbmltYXAsXG4gICAgICBoZWlnaHQ6IHNjZW5lU2l6ZS5oZWlnaHQgKiB0aGlzLnNjYWxlTWluaW1hcFxuICAgIH07XG5cbiAgICBjb25zdCBtaW5pbWFwT2Zmc2V0ID0gdGhpcy5taW5pbWFwT2Zmc2V0KCk7XG5cbiAgICAvLyBVcGRhdGUgdGhlIHNpemUgb2YgdGhlIG1pbmltYXAncyBzdmcsIHRoZSBidWZmZXIgY2FudmFzIGFuZCB0aGVcbiAgICAvLyB2aWV3cG9pbnQgcmVjdC5cbiAgICBzZWxlY3QodGhpcy5taW5pbWFwU3ZnKS5hdHRyKHRoaXMubWluaW1hcFNpemUgYXMgTnpTYWZlQW55KTtcbiAgICBzZWxlY3QodGhpcy5jYW52YXNCdWZmZXIpLmF0dHIodGhpcy5taW5pbWFwU2l6ZSBhcyBOelNhZmVBbnkpO1xuXG4gICAgaWYgKHRoaXMudHJhbnNsYXRlICE9IG51bGwgJiYgdGhpcy56b29tICE9IG51bGwpIHtcbiAgICAgIC8vIFVwZGF0ZSB0aGUgdmlld3BvaW50IHJlY3RhbmdsZSBzaGFwZSBzaW5jZSB0aGUgYXNwZWN0IHJhdGlvIG9mIHRoZVxuICAgICAgLy8gbWFwIGhhcyBjaGFuZ2VkLlxuICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHRoaXMuem9vbSgpKTtcbiAgICB9XG5cbiAgICAvLyBTZXJpYWxpemUgdGhlIG1haW4gc3ZnIHRvIGEgc3RyaW5nIHdoaWNoIHdpbGwgYmUgdXNlZCBhcyB0aGUgcmVuZGVyaW5nXG4gICAgLy8gY29udGVudCBmb3IgdGhlIGNhbnZhcy5cbiAgICBjb25zdCBzdmdYbWwgPSBuZXcgWE1MU2VyaWFsaXplcigpLnNlcmlhbGl6ZVRvU3RyaW5nKHRoaXMuc3ZnKTtcblxuICAgIC8vIE5vdyB0aGF0IHRoZSBzdmcgaXMgc2VyaWFsaXplZCBmb3IgcmVuZGVyaW5nLCByZW1vdmUgdGhlIHRlbXBvcmFyaWx5XG4gICAgLy8gYXNzaWduZWQgc3R5bGVzLCBleHBsaWNpdCB3aWR0aCBhbmQgaGVpZ2h0IGFuZCBicmluZyBiYWNrIHRoZSBwYW4vem9vbVxuICAgIC8vIHRyYW5zZm9ybS5cbiAgICBzdmdTdHlsZS5yZW1vdmUoKTtcbiAgICBzdmdTZWxlY3Rpb24uYXR0cignd2lkdGgnLCAnMTAwJScpLmF0dHIoJ2hlaWdodCcsICcxMDAlJyk7XG5cbiAgICB6b29tR1NlbGVjdGlvbi5hdHRyKCd0cmFuc2Zvcm0nLCB6b29tVHJhbnNmb3JtKTtcblxuICAgIGNvbnN0IGltYWdlID0gbmV3IEltYWdlKCk7XG4gICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgLy8gRHJhdyB0aGUgc3ZnIGNvbnRlbnQgb250byB0aGUgYnVmZmVyIGNhbnZhcy5cbiAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmNhbnZhc0J1ZmZlci5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgY29udGV4dCEuY2xlYXJSZWN0KDAsIDAsIHRoaXMuY2FudmFzQnVmZmVyLndpZHRoLCB0aGlzLmNhbnZhc0J1ZmZlci5oZWlnaHQpO1xuXG4gICAgICBjb250ZXh0IS5kcmF3SW1hZ2UoaW1hZ2UsIG1pbmltYXBPZmZzZXQueCwgbWluaW1hcE9mZnNldC55LCB0aGlzLm1pbmltYXBTaXplLndpZHRoLCB0aGlzLm1pbmltYXBTaXplLmhlaWdodCk7XG4gICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICAvLyBIaWRlIHRoZSBvbGQgY2FudmFzIGFuZCBzaG93IHRoZSBuZXcgYnVmZmVyIGNhbnZhcy5cbiAgICAgICAgc2VsZWN0KHRoaXMuY2FudmFzQnVmZmVyKS5zdHlsZSgnZGlzcGxheScsICdibG9jaycpO1xuICAgICAgICBzZWxlY3QodGhpcy5jYW52YXMpLnN0eWxlKCdkaXNwbGF5JywgJ25vbmUnKTtcbiAgICAgICAgLy8gU3dhcCB0aGUgdHdvIGNhbnZhc2VzLlxuICAgICAgICBbdGhpcy5jYW52YXMsIHRoaXMuY2FudmFzQnVmZmVyXSA9IFt0aGlzLmNhbnZhc0J1ZmZlciwgdGhpcy5jYW52YXNdO1xuICAgICAgfSk7XG4gICAgfTtcbiAgICBpbWFnZS5zcmMgPSAnZGF0YTppbWFnZS9zdmcreG1sO2NoYXJzZXQ9dXRmLTgsJyArIGVuY29kZVVSSUNvbXBvbmVudChzdmdYbWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgY2hhbmdlcyBpbiB6b29taW5nL3Bhbm5pbmcuIFNob3VsZCBiZSBjYWxsZWQgZnJvbSB0aGUgbWFpbiBzdmdcbiAgICogdG8gbm90aWZ5IHRoYXQgYSB6b29tL3BhbiB3YXMgcGVyZm9ybWVkIGFuZCB0aGlzIG1pbmltYXAgd2lsbCB1cGRhdGUgaXQnc1xuICAgKiB2aWV3cG9pbnQgcmVjdGFuZ2xlLlxuICAgKiBAcGFyYW0gdHJhbnNmb3JtXG4gICAqL1xuICB6b29tKHRyYW5zZm9ybT86IFpvb21UcmFuc2Zvcm0gfCBOelpvb21UcmFuc2Zvcm0pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zY2FsZU1pbmltYXAgPT0gbnVsbCkge1xuICAgICAgLy8gU2NlbmUgaXMgbm90IHJlYWR5IHlldC5cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gVXBkYXRlIHRoZSBuZXcgdHJhbnNsYXRlIGFuZCBzY2FsZSBwYXJhbXMsIG9ubHkgaWYgc3BlY2lmaWVkLlxuICAgIGlmICh0cmFuc2Zvcm0pIHtcbiAgICAgIHRoaXMudHJhbnNsYXRlID0gW3RyYW5zZm9ybS54LCB0cmFuc2Zvcm0ueV07XG4gICAgICB0aGlzLnNjYWxlTWFpbiA9IHRyYW5zZm9ybS5rO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSB0aGUgbG9jYXRpb24gb2YgdGhlIHZpZXdwb2ludCByZWN0YW5nbGUuXG4gICAgY29uc3Qgc3ZnUmVjdCA9IHRoaXMuc3ZnLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGNvbnN0IG1pbmltYXBPZmZzZXQgPSB0aGlzLm1pbmltYXBPZmZzZXQoKTtcbiAgICBjb25zdCB2aWV3cG9pbnRTZWxlY3Rpb24gPSBzZWxlY3QodGhpcy52aWV3cG9pbnQpO1xuICAgIHRoaXMudmlld3BvaW50Q29vcmQueCA9ICgtdGhpcy50cmFuc2xhdGVbMF0gKiB0aGlzLnNjYWxlTWluaW1hcCkgLyB0aGlzLnNjYWxlTWFpbjtcbiAgICB0aGlzLnZpZXdwb2ludENvb3JkLnkgPSAoLXRoaXMudHJhbnNsYXRlWzFdICogdGhpcy5zY2FsZU1pbmltYXApIC8gdGhpcy5zY2FsZU1haW47XG4gICAgY29uc3Qgdmlld3BvaW50V2lkdGggPSAoc3ZnUmVjdC53aWR0aCAqIHRoaXMuc2NhbGVNaW5pbWFwKSAvIHRoaXMuc2NhbGVNYWluO1xuICAgIGNvbnN0IHZpZXdwb2ludEhlaWdodCA9IChzdmdSZWN0LmhlaWdodCAqIHRoaXMuc2NhbGVNaW5pbWFwKSAvIHRoaXMuc2NhbGVNYWluO1xuICAgIHZpZXdwb2ludFNlbGVjdGlvblxuICAgICAgLmF0dHIoJ3gnLCB0aGlzLnZpZXdwb2ludENvb3JkLnggKyBtaW5pbWFwT2Zmc2V0LngpXG4gICAgICAuYXR0cigneScsIHRoaXMudmlld3BvaW50Q29vcmQueSArIG1pbmltYXBPZmZzZXQueSlcbiAgICAgIC5hdHRyKCd3aWR0aCcsIHZpZXdwb2ludFdpZHRoKVxuICAgICAgLmF0dHIoJ2hlaWdodCcsIHZpZXdwb2ludEhlaWdodCk7XG4gICAgLy8gU2hvdy9oaWRlIHRoZSBtaW5pbWFwIGRlcGVuZGluZyBvbiB0aGUgdmlld3BvaW50IGFyZWEgYXMgZnJhY3Rpb24gb2YgdGhlXG4gICAgLy8gd2hvbGUgbWluaW1hcC5cbiAgICBjb25zdCBtYXBXaWR0aCA9IHRoaXMubWluaW1hcFNpemUud2lkdGg7XG4gICAgY29uc3QgbWFwSGVpZ2h0ID0gdGhpcy5taW5pbWFwU2l6ZS5oZWlnaHQ7XG4gICAgY29uc3QgeCA9IHRoaXMudmlld3BvaW50Q29vcmQueDtcbiAgICBjb25zdCB5ID0gdGhpcy52aWV3cG9pbnRDb29yZC55O1xuICAgIGNvbnN0IHcgPSBNYXRoLm1pbihNYXRoLm1heCgwLCB4ICsgdmlld3BvaW50V2lkdGgpLCBtYXBXaWR0aCkgLSBNYXRoLm1pbihNYXRoLm1heCgwLCB4KSwgbWFwV2lkdGgpO1xuICAgIGNvbnN0IGggPSBNYXRoLm1pbihNYXRoLm1heCgwLCB5ICsgdmlld3BvaW50SGVpZ2h0KSwgbWFwSGVpZ2h0KSAtIE1hdGgubWluKE1hdGgubWF4KDAsIHkpLCBtYXBIZWlnaHQpO1xuICAgIGNvbnN0IGZyYWNJbnRlcnNlY3QgPSAodyAqIGgpIC8gKG1hcFdpZHRoICogbWFwSGVpZ2h0KTtcbiAgICBpZiAoZnJhY0ludGVyc2VjdCA8IEZSQUNfVklFV1BPSU5UX0FSRUEpIHtcbiAgICAgIHRoaXMubWluaW1hcC5jbGFzc0xpc3QucmVtb3ZlKCdoaWRkZW4nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5taW5pbWFwLmNsYXNzTGlzdC5hZGQoJ2hpZGRlbicpO1xuICAgIH1cbiAgfVxufVxuIl19