ng-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
204 lines • 34.9 kB
JavaScript
/**
* 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