Compare commits
1
Commits
78f1ae00aa
...
398f098b8b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
398f098b8b |
@@ -2,8 +2,8 @@ import {
|
||||
Component,
|
||||
ViewChild,
|
||||
ElementRef,
|
||||
ChangeDetectionStrategy,
|
||||
HostListener,
|
||||
ChangeDetectionStrategy,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
nameof,
|
||||
@@ -122,6 +122,40 @@ export class XChartComponent extends XChartContainerComponent {
|
||||
this.registerActionProvider();
|
||||
}
|
||||
|
||||
//
|
||||
// Available Action Bar Items Changed ...
|
||||
const isAvailableActionBarItemsChanged = changeKeys.includes(
|
||||
nameof<XChartComponent>('availableActionBarItems')
|
||||
);
|
||||
if (isAvailableActionBarItemsChanged) {
|
||||
//
|
||||
if (isNullOrUndefined(this.availableActionBarItems)) {
|
||||
this.availableActionBarItems = this.propertyProvider.availableActionBarItems;
|
||||
}
|
||||
|
||||
//
|
||||
await this.prepareActionBar();
|
||||
}
|
||||
|
||||
//
|
||||
// Zoom Step ...
|
||||
const isZoomStepChanged = changeKeys.includes(
|
||||
nameof<XChartComponent>('zoomStep')
|
||||
);
|
||||
if (isZoomStepChanged) {
|
||||
//
|
||||
let zoomStep = await this.getValueAsync(this.zoomStep);
|
||||
if (isNullOrUndefined(zoomStep) ||
|
||||
zoomStep < 0 ||
|
||||
zoomStep > 1
|
||||
) {
|
||||
this.zoomStep = 0.125;
|
||||
}
|
||||
|
||||
//
|
||||
zoomStep = await this.getValueAsync(this.zoomStep);
|
||||
}
|
||||
|
||||
//
|
||||
// Check Auto Update ...
|
||||
var autoUpdate = await this.getValueAsync(this.autoUpdate);
|
||||
@@ -207,47 +241,82 @@ export class XChartComponent extends XChartContainerComponent {
|
||||
}
|
||||
|
||||
//
|
||||
switch (
|
||||
model.action
|
||||
switch (model.action) {
|
||||
//
|
||||
// case this.ActionBarItems.ChangeMode:
|
||||
// this.handleActionModeFired(model.event);
|
||||
// break;
|
||||
// Print ...
|
||||
case XChartActionBarItem.Print:
|
||||
await this.handlePrint();
|
||||
break;
|
||||
|
||||
// //
|
||||
// case this.ActionBarItems.ChangeTheme:
|
||||
// this.handleActionThemFired(model.event);
|
||||
// break;
|
||||
//
|
||||
// Export As CSV ...
|
||||
case XChartActionBarItem.ExportAsCSV:
|
||||
await this.handleExportAsCSV();
|
||||
break;
|
||||
|
||||
// //
|
||||
// case this.ActionBarItems.Close:
|
||||
// this.closeTab(this.currentTab);
|
||||
// break;
|
||||
//
|
||||
// Export As PNG ...
|
||||
case XChartActionBarItem.ExportAsPNG:
|
||||
await this.handleExportAsPng();
|
||||
break;
|
||||
|
||||
// //
|
||||
// case this.ActionBarItems.Undo:
|
||||
// this.undo();
|
||||
// break;
|
||||
//
|
||||
// Export As SVG ...
|
||||
case XChartActionBarItem.ExportAsSVG:
|
||||
await this.handleExportAsSVG();
|
||||
break;
|
||||
|
||||
// //
|
||||
// case this.ActionBarItems.Redo:
|
||||
// this.redo();
|
||||
// break;
|
||||
//
|
||||
// Zoom In ...
|
||||
case XChartActionBarItem.ZoomIn:
|
||||
await this.handleZoomIn();
|
||||
break;
|
||||
|
||||
// //
|
||||
// case this.ActionBarItems.Beautify:
|
||||
// await this.beautifyCode();
|
||||
// break;
|
||||
//
|
||||
// Zoom Out ...
|
||||
case XChartActionBarItem.ZoomOut:
|
||||
await this.handleZoomOut();
|
||||
break;
|
||||
|
||||
// //
|
||||
// case this.ActionBarItems.Save:
|
||||
// //
|
||||
// this.updateCurrentTabDescriptor({
|
||||
// canSave: false,
|
||||
// });
|
||||
// this.prepareActionBar();
|
||||
// break;
|
||||
) {
|
||||
//
|
||||
// Zoom Selection ...
|
||||
case XChartActionBarItem.ZoomSelection:
|
||||
break;
|
||||
|
||||
//
|
||||
// X Selection ...
|
||||
case XChartActionBarItem.XSelection:
|
||||
break;
|
||||
|
||||
//
|
||||
// Y Selection ...
|
||||
case XChartActionBarItem.YSelection:
|
||||
break;
|
||||
|
||||
//
|
||||
// XY Selection ...
|
||||
case XChartActionBarItem.XYSelection:
|
||||
break;
|
||||
|
||||
//
|
||||
// Pan ...
|
||||
case XChartActionBarItem.Pan:
|
||||
await this.handlePan();
|
||||
break;
|
||||
|
||||
//
|
||||
// ResetChart ...
|
||||
case XChartActionBarItem.ResetChart:
|
||||
await this.handleResetChart();
|
||||
break;
|
||||
|
||||
//
|
||||
// ToggleFullScreen ...
|
||||
case XChartActionBarItem.ToggleFullScreen:
|
||||
await this.handleToggleFullscreen();
|
||||
break;
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
@@ -308,6 +377,222 @@ export class XChartComponent extends XChartContainerComponent {
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Toolbar Actions ...
|
||||
async handleExportAsPng() {
|
||||
//
|
||||
if (isNullOrUndefined(this.chartInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
await this.export('png');
|
||||
}
|
||||
|
||||
async handleExportAsSVG() {
|
||||
//
|
||||
if (isNullOrUndefined(this.chartInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
await this.export('svg');
|
||||
}
|
||||
|
||||
async handleExportAsCSV() {
|
||||
//
|
||||
if (isNullOrUndefined(this.chartInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
await this.export('csv');
|
||||
}
|
||||
|
||||
async handleZoomIn() {
|
||||
//
|
||||
if (isNullOrUndefined(this.chartInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
var zoomStep = await this.getValueAsync(this.zoomStep);
|
||||
|
||||
//
|
||||
const state = this.chartInstance.getState();
|
||||
const minX = state.minX;
|
||||
const maxX = state.maxX;
|
||||
const rangeIn = maxX - minX;
|
||||
|
||||
//
|
||||
await this.chartInstance.zoomX(minX + rangeIn * zoomStep, maxX - rangeIn * zoomStep);
|
||||
}
|
||||
|
||||
async handleZoomOut() {
|
||||
//
|
||||
if (isNullOrUndefined(this.chartInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
var zoomStep = await this.getValueAsync(this.zoomStep);
|
||||
|
||||
//
|
||||
const state = this.chartInstance.getState();
|
||||
const minX = state.minX;
|
||||
const maxX = state.maxX;
|
||||
const rangeIn = maxX - minX;
|
||||
|
||||
//
|
||||
await this.chartInstance.zoomX(minX - rangeIn * zoomStep, maxX + rangeIn * zoomStep);
|
||||
}
|
||||
|
||||
async handlePan() {
|
||||
//
|
||||
if (isNullOrUndefined(this.chartInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
await this.chartInstance.updateOptions({
|
||||
chart: {
|
||||
zoom: {
|
||||
enabled: false
|
||||
},
|
||||
selection: {
|
||||
type: 'x',
|
||||
enabled: true,
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async handleResetChart() {
|
||||
//
|
||||
if (isNullOrUndefined(this.chartInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
this.chartInstance.resetSeries(true, true);
|
||||
}
|
||||
|
||||
async handlePrint() {
|
||||
//
|
||||
if (isNullOrUndefined(this.chartInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
const result = await this.chartInstance.dataURI();
|
||||
if ('imgURI' in result) {
|
||||
//
|
||||
const imgURI = result.imgURI;
|
||||
const printWindow = window.open('', '_blank');
|
||||
if (printWindow) {
|
||||
//
|
||||
// Write Data Uri on a Page for Printing ...
|
||||
printWindow.document.write(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Print Chart</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
@media print {
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img src="${imgURI}" alt="Chart" />
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window.print();
|
||||
window.onafterprint = function() {
|
||||
window.close();
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
|
||||
//
|
||||
printWindow.document.close();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
|
||||
async handleToggleFullscreen() {
|
||||
//
|
||||
if (isNullOrUndefined(this.chartInstance) ||
|
||||
isNullOrUndefined(this.chartContainer) ||
|
||||
isNullOrUndefined(this.chartContainer.nativeElement)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const chartWrapper = this.chartContainer.nativeElement;
|
||||
const doc = document as any;
|
||||
|
||||
//
|
||||
// Check if the chart wrapper is currently in fullscreen mode
|
||||
const isFullscreen =
|
||||
doc.fullscreenElement === chartWrapper ||
|
||||
doc.msFullscreenElement === chartWrapper ||
|
||||
doc.mozFullScreenElement === chartWrapper ||
|
||||
doc.webkitFullscreenElement === chartWrapper;
|
||||
if (!isFullscreen) {
|
||||
//
|
||||
// Enter Fullscreen
|
||||
if (chartWrapper.requestFullscreen) {
|
||||
await chartWrapper.requestFullscreen();
|
||||
} else if (chartWrapper.webkitRequestFullscreen) {
|
||||
await chartWrapper.webkitRequestFullscreen();
|
||||
} else if (chartWrapper.mozRequestFullScreen) {
|
||||
await chartWrapper.mozRequestFullScreen();
|
||||
} else if (chartWrapper.msRequestFullscreen) {
|
||||
await chartWrapper.msRequestFullscreen();
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Exit Fullscreen
|
||||
if (doc.exitFullscreen) {
|
||||
await doc.exitFullscreen();
|
||||
} else if (doc.webkitExitFullscreen) {
|
||||
await doc.webkitExitFullscreen();
|
||||
} else if (doc.mozCancelFullScreen) {
|
||||
await doc.mozCancelFullScreen();
|
||||
} else if (doc.msExitFullscreen) {
|
||||
await doc.msExitFullscreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private ...
|
||||
private async initializeComponent() {
|
||||
|
||||
@@ -22,27 +22,26 @@ import {
|
||||
XCardActionModel,
|
||||
XComponentCardContainer,
|
||||
IXComponentCardContainer,
|
||||
XComponentCardContainerComponent,
|
||||
} from '../x-card/x-card.typings';
|
||||
import { concatMap, map } from 'rxjs/operators';
|
||||
import { map } from 'rxjs/operators';
|
||||
import {
|
||||
XBaseContainer,
|
||||
XBaseContainerComponent,
|
||||
} from '../classes/i-x-base.container';
|
||||
import {
|
||||
XActionBarItem,
|
||||
XActionBarActionModel,
|
||||
XActionBarActionFiredModel,
|
||||
XComponentActionBarContainer,
|
||||
IXComponentActionBarContainer,
|
||||
} from '../x-action-bar/x-action-bar.typings';
|
||||
import { forkJoin, Observable, Subject } from 'rxjs';
|
||||
import { ViewportRuler } from '@angular/cdk/overlay';
|
||||
import { XManagerService } from 'x-framework-services';
|
||||
import { XBaseActionModel } from '../classes/x-base-action.model';
|
||||
import { X_FRAMEWORK_COMPONENTS_CONFIG } from '../tokens/x-injectable-tokens';
|
||||
import { XFrameworkComponentsConfig } from '../config/x-framework-components.config';
|
||||
import {
|
||||
IXComponentActionBarContainer,
|
||||
XActionBarActionFiredModel,
|
||||
XActionBarActionModel,
|
||||
XActionBarItem,
|
||||
XComponentActionBarContainer,
|
||||
} from '../x-action-bar/x-action-bar.typings';
|
||||
import { XPopoverPresentOptions } from '../dialogs/x-popover/x-popover.typings';
|
||||
import {
|
||||
XBaseContainer,
|
||||
XBaseContainerComponent,
|
||||
} from '../classes/i-x-base.container';
|
||||
import { XFrameworkComponentsConfig } from '../config/x-framework-components.config';
|
||||
|
||||
//
|
||||
//#region Chart ...
|
||||
@@ -3300,8 +3299,7 @@ export interface IXChartContainer extends TXChartContainer {
|
||||
autoUpdate: XStandardType<boolean>;
|
||||
options: XStandardType<XChartOptions>;
|
||||
series: XStandardType<XChartSeriesType>;
|
||||
|
||||
//
|
||||
zoomStep: XStandardType<number>;
|
||||
type: XStandardType<XChartTypeIdentifier>;
|
||||
|
||||
//
|
||||
@@ -3324,14 +3322,16 @@ export interface IXChartContainer extends TXChartContainer {
|
||||
})
|
||||
export class XChartContainer
|
||||
extends XBaseContainer
|
||||
implements Readonly<IXChartContainer>
|
||||
{
|
||||
implements Readonly<IXChartContainer> {
|
||||
//
|
||||
readonly actionProvider = new Subject<XChartActionModel>();
|
||||
readonly cssClass: XStandardType<XOneOrManyType<string>>;
|
||||
|
||||
//
|
||||
readonly options: XStandardType<XChartOptions>;
|
||||
readonly zoomStep: XStandardType<number> = 0.125;
|
||||
readonly series: XStandardType<XChartSeriesType>;
|
||||
readonly autoUpdate: XStandardType<boolean> = true;
|
||||
readonly cssClass: XStandardType<XOneOrManyType<string>>;
|
||||
readonly actionProvider = new Subject<XChartActionModel>();
|
||||
readonly type: XStandardType<XChartTypeIdentifier> = XChartType.Line;
|
||||
|
||||
//
|
||||
@@ -3403,8 +3403,7 @@ export class XChartContainer
|
||||
@Component({ template: `` })
|
||||
export abstract class XChartContainerComponent
|
||||
extends XBaseContainerComponent
|
||||
implements IXChartContainer
|
||||
{
|
||||
implements IXChartContainer {
|
||||
//
|
||||
//#region Props ...
|
||||
@Input()
|
||||
@@ -3427,6 +3426,9 @@ export abstract class XChartContainerComponent
|
||||
@Input()
|
||||
series: XStandardType<XChartSeriesType> = this.propertyProvider.series;
|
||||
|
||||
@Input()
|
||||
zoomStep: XStandardType<number> = this.propertyProvider.zoomStep;
|
||||
|
||||
@Input()
|
||||
autoUpdate: XStandardType<boolean> = this.propertyProvider.autoUpdate;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user