UNPKG

igniteui-angular-charts

Version:

Ignite UI Angular charting components for building rich data visualizations for modern web apps.

583 lines (574 loc) 24.3 kB
import { Component, ChangeDetectionStrategy, ViewChild, ViewContainerRef, Input, EventEmitter, Output, ContentChildren } from '@angular/core'; import { AngularRenderer, AngularWrapper } from "igniteui-angular-core"; import { TypeRegistrar, delegateCombine } from "igniteui-angular-core"; import { DataChartStylingDefaults } from './DataChartStylingDefaults'; import { XamDoughnutChart } from './XamDoughnutChart'; import { ensureBool, fromPoint, CollectionAdapter, toSpinal, initializePropertiesFromCss, NamePatcher } from "igniteui-angular-core"; import { Style } from "igniteui-angular-core"; import { IgxSliceClickEventArgs } from "./igx-slice-click-event-args"; import { IgxHoleDimensionsChangedEventArgs } from "./igx-hole-dimensions-changed-event-args"; import { IgxRingSeriesBaseComponent } from "./igx-ring-series-base-component"; import { NotifyCollectionChangedAction } from "igniteui-angular-core"; import { IgxRingSeriesCollection } from "./igx-ring-series-collection"; import { IgxPieSliceDataContext } from "./igx-pie-slice-data-context"; import * as i0 from "@angular/core"; /** * Represents concentric circles divided on arcs depending on data. */ export let IgxDoughnutChartComponent = /*@__PURE__*/ (() => { class IgxDoughnutChartComponent { constructor(renderer, _elRef, ngZone, injector, componentFactoryResolver) { this.renderer = renderer; this._elRef = _elRef; this.ngZone = ngZone; this.injector = injector; this.componentFactoryResolver = componentFactoryResolver; /** * The series actually present in the chart. Do not directly modify this array. * This array's contents can be modified by causing Angular to reproject the child content. * Or adding and removing series from the manual series collection on the series property. */ this.actualSeries = []; this._seriesAdapter = null; this._series = null; this._defaultTooltips = null; this.__p = null; this._hasUserValues = new Set(); this._stylingContainer = null; this._stylingParent = null; this._inStyling = false; this._sliceClick = null; this._holeDimensionsChanged = null; this._zoneRunner = null; if (this._styling) { NamePatcher.ensureStylablePatched(Object.getPrototypeOf(this)); } this._implementation = this.createImplementation(); this._implementation.externalObject = this; this.onImplementationCreated(); this._zoneRunner = (act) => ngZone.run(act); this.container = renderer.createElement("div"); renderer.appendChild(_elRef.element.nativeElement, this.container); renderer.setStyle(this.container, "display", "block"); renderer.setStyle(this.container, "width", "100%"); renderer.setStyle(this.container, "height", "100%"); var root; root = this.container; if (this.container != null) { root = this.container; } var ren = new AngularRenderer(root, this.renderer, window.document, this.ngZone, true, DataChartStylingDefaults); this._wrapper = ren; var chart = this.i; this._chart = chart; this._seriesAdapter = new CollectionAdapter([], this.i.series, this.actualSeries, (c) => c.i, (i) => { i.owner = this; // (<any>i)._provideRenderer(this._dataSource); if (this.container && this.container.parentElement) { i._styling(this.container, this, this); } this._ensureDefaultTooltip(i); this._ensureTooltipCreated(i); }, (i) => { //(<any>i)._provideRenderer(null); }); chart.provideContainer(ren); ren.addSizeWatcher(() => { this._chart.notifyResized(); }); } set height(value) { this._height = value; this.renderer.setStyle(this._elRef.element.nativeElement, "height", value); this._chart.notifyResized(); } get height() { return this._height; } set width(value) { this._width = value; this.renderer.setStyle(this._elRef.element.nativeElement, "width", value); this._chart.notifyResized(); } get width() { return this._width; } ngOnDestroy() { this._chart.destroy(); this._wrapper.destroy(); } onImplementationCreated() { } createImplementation() { return new XamDoughnutChart(); } get i() { return this._implementation; } createSeriesComponent(type) { if (TypeRegistrar.isRegistered(type)) { let s = TypeRegistrar.create(type); s.owner = this; s._provideRenderer(this._wrapper); return s; } else { //we shouldn't get here, hopefully. throw Error("series type not loaded: " + type); } } ngAfterContentInit() { if (TypeRegistrar.isRegistered("IgxDoughnutChartDefaultTooltipsComponent")) { let c = TypeRegistrar.get("IgxDoughnutChartDefaultTooltipsComponent"); let cf = this.componentFactoryResolver.resolveComponentFactory(c); let cr = this._dynamicContent.createComponent(cf); this._defaultTooltips = cr; cr.instance.onContentReady.subscribe(() => { this._onDefaultTooltipsReady(cr); }); } this._seriesAdapter.updateQuery(this.contentSeries); } ngAfterViewInit() { this.updateStyle(); this.i.notifyResized(); } updateStyle() { this._styling(this.container, this); if (this.actualSeries && this.actualSeries.length > 0) { var currSeries = this.actualSeries; for (var i = 0; i < currSeries.length; i++) { currSeries[i]._styling(this.container, this, this); } } } /** * A collection or manually added series for the chart. */ get series() { if (this._series === null) { let coll = new IgxRingSeriesCollection(); let inner = coll._innerColl; inner.addListener((sender, e) => { switch (e.action) { case NotifyCollectionChangedAction.Add: this._seriesAdapter.addManualItem(e.newItems.item(0)); break; case NotifyCollectionChangedAction.Remove: this._seriesAdapter.removeManualItemAt(e.oldStartingIndex); break; case NotifyCollectionChangedAction.Replace: this._seriesAdapter.removeManualItemAt(e.oldStartingIndex); this._seriesAdapter.insertManualItem(e.newStartingIndex, e.newItems.item(0)); break; case NotifyCollectionChangedAction.Reset: this._seriesAdapter.clearManualItems(); break; } }); this._series = coll; } return this._series; } _ensureTooltipCreated(series) { series._ensureTooltipCreated(() => this.createTooltip(), (ele) => { let wrapper = new AngularWrapper(ele, this.renderer, this.ngZone); wrapper.updateToolTip = ele.updateToolTip; wrapper.hideToolTip = ele.hideToolTip; return wrapper; }); } _ensureDefaultTooltip(series) { if (this._defaultTooltips == null) { return; } this._defaultTooltips.instance["ensureDefaultTooltip"](series); } _onDefaultTooltipsReady(cr) { if (this.actualSeries && this.actualSeries.length > 0) { var currSeries = this.actualSeries; for (var i = 0; i < currSeries.length; i++) { if (currSeries[i].showDefaultTooltip) { this._ensureDefaultTooltip(currSeries[i]); } } } } createTooltip() { if (!TypeRegistrar.isRegistered("IgxTooltipContainerComponent")) { return null; } let t = TypeRegistrar.get("IgxTooltipContainerComponent"); let cf = this.componentFactoryResolver.resolveComponentFactory(t); let cr = this._dynamicContent.createComponent(cf); let ele = cr.location.nativeElement; let self = this; ele.updateToolTip = function (c) { if (c.externalObject) { c = c.externalObject; } else { let ext = new IgxPieSliceDataContext(); ext._implementation = c; c = ext; } if (ele.parentElement != self.container) { if (ele.parentElement != null) { ele.parentElement.removeChild(ele); } self.container.appendChild(ele); } cr.instance.context = c; if (c.series.showDefaultTooltip) { var tooltipContainers = ele.getElementsByClassName("ui-tooltip-container"); if (tooltipContainers.length > 0) tooltipContainers[0].style.borderColor = c.i.slice.background.fill; } ele.style.display = "block"; return true; }; ele.hideToolTip = function () { ele.style.display = "none"; }; ele.style.display = "none"; return cr; } /** * Gets or sets whether the slices can be selected. */ get allowSliceSelection() { return this.i.aw; } set allowSliceSelection(v) { this.i.aw = ensureBool(v); } /** * Gets or sets whether all surface interactions with the plot area should be disabled. */ get isSurfaceInteractionDisabled() { return this.i.ax; } set isSurfaceInteractionDisabled(v) { this.i.ax = ensureBool(v); } /** * Gets or sets whether the slices can be exploded. */ get allowSliceExplosion() { return this.i.av; } set allowSliceExplosion(v) { this.i.av = ensureBool(v); } /** * Gets or sets the inner extent of the doughnut chart. It is percent from the outer ring's radius. */ get innerExtent() { return this.i.a3; } set innerExtent(v) { this.i.a3 = +v; } /** * Gets or sets the fill brush. */ get selectedSliceFill() { return this.i.cg ? this.i.cg.fill : null; } set selectedSliceFill(v) { this.ensureSelectedStyle(); this.i.cg.fill = v; } /** * Gets or sets the stroke brush. */ get selectedSliceStroke() { return this.i.cg ? this.i.cg.stroke : null; } set selectedSliceStroke(v) { this.ensureSelectedStyle(); this.i.cg.stroke = v; } /** * Gets or sets the stroke thickness. */ get selectedSliceStrokeThickness() { return this.i.cg ? this.i.cg.strokeThickness : NaN; } set selectedSliceStrokeThickness(v) { this.ensureSelectedStyle(); this.i.cg.strokeThickness = +v; } /** * Gets or sets the opacity. */ get selectedSliceOpacity() { return this.i.cg ? this.i.cg.opacity : NaN; } set selectedSliceOpacity(v) { this.ensureSelectedStyle(); this.i.cg.opacity = +v; } ensureSelectedStyle() { if (this.i.cg) { return; } this.i.cg = new Style(); } /** * Gets or sets the scaling value used to affect the pixel density of the control. * A higher scaling ratio will produce crisper visuals at the expense of memory. Lower values will cause the control * to appear blurry. */ get pixelScalingRatio() { return this.i.a4; } set pixelScalingRatio(v) { this.i.a4 = +v; } /** * Resolved pixel scaling ratio. Unless explicitly overridden by the * IgxDoughnutChart.PixelScalingRatioComponent property, * this one returns the default ratio enforced by device. High resolution devices will initialize this property * to a higher value. */ get actualPixelScalingRatio() { return this.i.a1; } set actualPixelScalingRatio(v) { this.i.a1 = +v; } findByName(name) { if (this.findEphemera) { if (name && name.indexOf("@@e:") == 0) { return this.findEphemera(name); } } if (this.series != null && this.series.findByName && this.series.findByName(name)) { return this.series.findByName(name); } return null; } get hasUserValues() { return this._hasUserValues; } __m(propertyName) { if (!this._inStyling) { this._hasUserValues.add(propertyName); } } _styling(container, component, parent) { if (this._inStyling) { return; } this._inStyling = true; this._stylingContainer = container; this._stylingParent = component; let genericPrefix = ""; let typeName = this.i.$type.name; if (typeName.indexOf("Xam") === 0) { typeName = typeName.substring(3); } genericPrefix = toSpinal("DoughnutChartComponent"); let additionalPrefixes = []; let prefix = toSpinal(typeName); additionalPrefixes.push(prefix + "-"); let b = this.i.$type.baseType; while (b && b.name != "Object" && b.name != "Base" && b.name != "Control" && b.Name != "DependencyObject" && b.Name != "FrameworkElement") { typeName = b.name; if (typeName.indexOf("Xam") === 0) { typeName = typeName.substring(3); } let basePrefix = toSpinal(typeName); additionalPrefixes.push(basePrefix + "-"); b = b.baseType; } if (parent) { let parentTypeName = parent.i.$type.name; if (parentTypeName.indexOf("Xam") === 0) { parentTypeName = parentTypeName.substring(3); } let parentPrefix = toSpinal(parentTypeName); additionalPrefixes.push(parentPrefix + "-" + genericPrefix + "-"); additionalPrefixes.push(parentPrefix + "-" + prefix + "-"); } initializePropertiesFromCss(container, this, genericPrefix + "-", this.hasUserValues, false, additionalPrefixes); if (this._otherStyling) { this._otherStyling(container, component, parent); } this._inStyling = false; } /** * Called by the UI framework to provide a UI container for rendering this control. * @param container * The UI container element. */ provideContainer(container) { this.i.provideContainer(container); } /** * Called when the control has been resized. */ notifyResized() { this.i.notifyResized(); } /** * Gets the ID of the UI container. */ getContainerID() { let iv = this.i.bd(); return (iv); } /** * Gets the center coordinates of the doughnut chart's center presenter. */ getCenterCoordinates() { let iv = this.i.cf(); return fromPoint(iv); } /** * Gets the hole radius of the doughnut chart's center presenter. */ getHoleRadius() { let iv = this.i.a2(); return (iv); } /** * Use to force the doughnut chart to finish any deferred work before printing or evaluating its visual. * This should only be called if the visual of the doughnut chart needs to be synchronously saved or evaluated. * Calling this method too often will hinder the performance of the doughnut chart. */ flush() { this.i.bk(); } /** * Returns the chart visuals expressed as a serialized string. */ exportSerializedVisualData() { let iv = this.i.bc(); return (iv); } notifyInsertItem(source_, index, newItem) { this.i.bm(source_, index, newItem); } notifySetItem(source_, index, oldItem, newItem) { this.i.bp(source_, index, oldItem, newItem); } /** * Used to manually notify the chart that the data source has reset or cleared its items. */ notifyClearItems(source_) { this.i.bl(source_); } notifyRemoveItem(source_, index, oldItem) { this.i.bn(source_, index, oldItem); } /** * Raised when the slice is clicked. */ get sliceClick() { if (this._sliceClick == null) { this._sliceClick = new EventEmitter(); this.i.sliceClick = delegateCombine(this.i.sliceClick, (o, e) => { this._runInZone(() => { let outerArgs = new IgxSliceClickEventArgs(); outerArgs._provideImplementation(e); if (this.beforeSliceClick) { this.beforeSliceClick(this, outerArgs); } this._sliceClick.emit({ sender: this, args: outerArgs }); }); }); } return this._sliceClick; } /** * Raised when the dimensions (center point or radius) of the doughnut hole change. */ get holeDimensionsChanged() { if (this._holeDimensionsChanged == null) { this._holeDimensionsChanged = new EventEmitter(); this.i.holeDimensionsChanged = delegateCombine(this.i.holeDimensionsChanged, (o, e) => { this._runInZone(() => { let outerArgs = new IgxHoleDimensionsChangedEventArgs(); outerArgs._provideImplementation(e); if (this.beforeHoleDimensionsChanged) { this.beforeHoleDimensionsChanged(this, outerArgs); } this._holeDimensionsChanged.emit({ sender: this, args: outerArgs }); }); }); } return this._holeDimensionsChanged; } _runInZone(act) { if (this._zoneRunner != null) { this._zoneRunner(act); } else { act(); } } } IgxDoughnutChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: IgxDoughnutChartComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ViewContainerRef }, { token: i0.NgZone }, { token: i0.Injector }, { token: i0.ComponentFactoryResolver }], target: i0.ɵɵFactoryTarget.Component }); IgxDoughnutChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: IgxDoughnutChartComponent, selector: "igx-doughnut-chart", inputs: { height: "height", width: "width", allowSliceSelection: "allowSliceSelection", isSurfaceInteractionDisabled: "isSurfaceInteractionDisabled", allowSliceExplosion: "allowSliceExplosion", innerExtent: "innerExtent", selectedSliceFill: "selectedSliceFill", selectedSliceStroke: "selectedSliceStroke", selectedSliceStrokeThickness: "selectedSliceStrokeThickness", selectedSliceOpacity: "selectedSliceOpacity", pixelScalingRatio: "pixelScalingRatio", actualPixelScalingRatio: "actualPixelScalingRatio" }, outputs: { sliceClick: "sliceClick", holeDimensionsChanged: "holeDimensionsChanged" }, host: { classAttribute: "ig-doughnut-chart igx-doughnut-chart" }, providers: [], queries: [{ propertyName: "contentSeries", predicate: IgxRingSeriesBaseComponent }], viewQueries: [{ propertyName: "_dynamicContent", first: true, predicate: ["dynamicContent"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: `<ng-container #dynamicContent></ng-container>`, isInline: true, styles: ["\n\t\t:host {\n\t\t\tdisplay: block;\n\t\t}\n\t"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); return IgxDoughnutChartComponent; })(); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: IgxDoughnutChartComponent, decorators: [{ type: Component, args: [{ selector: 'igx-doughnut-chart', template: `<ng-container #dynamicContent></ng-container>`, changeDetection: ChangeDetectionStrategy.OnPush, providers: [], host: { 'class': 'ig-doughnut-chart igx-doughnut-chart' }, styles: [` :host { display: block; } `] }] }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ViewContainerRef }, { type: i0.NgZone }, { type: i0.Injector }, { type: i0.ComponentFactoryResolver }]; }, propDecorators: { contentSeries: [{ type: ContentChildren, args: [IgxRingSeriesBaseComponent] }], _dynamicContent: [{ type: ViewChild, args: ["dynamicContent", { read: ViewContainerRef, static: true }] }], height: [{ type: Input }], width: [{ type: Input }], allowSliceSelection: [{ type: Input }], isSurfaceInteractionDisabled: [{ type: Input }], allowSliceExplosion: [{ type: Input }], innerExtent: [{ type: Input }], selectedSliceFill: [{ type: Input }], selectedSliceStroke: [{ type: Input }], selectedSliceStrokeThickness: [{ type: Input }], selectedSliceOpacity: [{ type: Input }], pixelScalingRatio: [{ type: Input }], actualPixelScalingRatio: [{ type: Input }], sliceClick: [{ type: Output }], holeDimensionsChanged: [{ type: Output }] } });