mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-15 12:09:44 +02:00
Able to draw till axis from chart configuration
- there is some issue with drawing the plot from chart data
This commit is contained in:
@@ -16,11 +16,23 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>XY Charts demos</h1>
|
<h1>XY Charts demos</h1>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
xychart
|
xychart-beta horizontal
|
||||||
|
title Basic xychart
|
||||||
|
x-axis "this is x axis" [category1, "category 2", category3]
|
||||||
|
y-axis yaxisText 10 --> 150
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<h1>XY Charts demos</h1>
|
||||||
|
<pre class="mermaid">
|
||||||
|
xychart-beta
|
||||||
|
title Basic xychart
|
||||||
|
x-axis "this is x axis" [category1, "category 2", category3]
|
||||||
|
y-axis yaxisText 10 --> 150
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<hr />
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from './mermaid.esm.mjs';
|
import mermaid from './mermaid.esm.mjs';
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
|
@@ -150,6 +150,7 @@ export interface MermaidConfig {
|
|||||||
er?: ErDiagramConfig;
|
er?: ErDiagramConfig;
|
||||||
pie?: PieDiagramConfig;
|
pie?: PieDiagramConfig;
|
||||||
quadrantChart?: QuadrantChartConfig;
|
quadrantChart?: QuadrantChartConfig;
|
||||||
|
xyChart?: XYChartConfig;
|
||||||
requirement?: RequirementDiagramConfig;
|
requirement?: RequirementDiagramConfig;
|
||||||
mindmap?: MindmapDiagramConfig;
|
mindmap?: MindmapDiagramConfig;
|
||||||
gitGraph?: GitGraphDiagramConfig;
|
gitGraph?: GitGraphDiagramConfig;
|
||||||
@@ -703,6 +704,37 @@ export interface QuadrantChartConfig extends BaseDiagramConfig {
|
|||||||
*/
|
*/
|
||||||
quadrantExternalBorderStrokeWidth?: number;
|
quadrantExternalBorderStrokeWidth?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface XYChartAxisConfig {
|
||||||
|
showLabel: boolean;
|
||||||
|
labelFontSize: number;
|
||||||
|
lablePadding: number;
|
||||||
|
labelFill: string;
|
||||||
|
showTitle: boolean;
|
||||||
|
titleFontSize: number;
|
||||||
|
titlePadding: number;
|
||||||
|
titleFill: string;
|
||||||
|
showTick: boolean;
|
||||||
|
tickLength: number;
|
||||||
|
tickWidth: number;
|
||||||
|
tickFill: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface XYChartConfig extends BaseDiagramConfig {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
fontFamily: string;
|
||||||
|
titleFontSize: number;
|
||||||
|
titleFill: string;
|
||||||
|
titlePadding: number;
|
||||||
|
showtitle: boolean;
|
||||||
|
xAxis: XYChartAxisConfig;
|
||||||
|
yAxis: XYChartAxisConfig;
|
||||||
|
plotBorderWidth: number;
|
||||||
|
chartOrientation: 'vertical' | 'horizontal';
|
||||||
|
plotReservedSpacePercent: number;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The object containing configurations specific for entity relationship diagrams
|
* The object containing configurations specific for entity relationship diagrams
|
||||||
*
|
*
|
||||||
|
@@ -9,41 +9,6 @@ export interface ChartComponent {
|
|||||||
getDrawableElements(): DrawableElem[];
|
getDrawableElements(): DrawableElem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum OrientationEnum {
|
|
||||||
VERTICAL = 'vertical',
|
|
||||||
HORIZONTAL = 'horizontal',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AxisConfig {
|
|
||||||
showLabel: boolean;
|
|
||||||
labelFontSize: number;
|
|
||||||
lablePadding: number;
|
|
||||||
labelFill: string;
|
|
||||||
showTitle: boolean;
|
|
||||||
titleFontSize: number;
|
|
||||||
titlePadding: number;
|
|
||||||
titleFill: string;
|
|
||||||
showTick: boolean;
|
|
||||||
tickLength: number;
|
|
||||||
tickWidth: number;
|
|
||||||
tickFill: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface XYChartConfig {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
fontFamily: string;
|
|
||||||
titleFontSize: number;
|
|
||||||
titleFill: string;
|
|
||||||
titlePadding: number;
|
|
||||||
showtitle: boolean;
|
|
||||||
xAxis: AxisConfig;
|
|
||||||
yAxis: AxisConfig;
|
|
||||||
plotBorderWidth: number;
|
|
||||||
chartOrientation: OrientationEnum;
|
|
||||||
plotReservedSpacePercent: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SimplePlotDataType = [string | number, number][];
|
export type SimplePlotDataType = [string | number, number][];
|
||||||
|
|
||||||
export interface LinePlotData {
|
export interface LinePlotData {
|
||||||
@@ -74,6 +39,11 @@ export interface LinearAxisDataType{
|
|||||||
|
|
||||||
export type AxisDataType = LinearAxisDataType | BandAxisDataType;
|
export type AxisDataType = LinearAxisDataType | BandAxisDataType;
|
||||||
|
|
||||||
|
export function isBandAxisData(data: any): data is BandAxisDataType {
|
||||||
|
return data.categories && Array.isArray(data.categories);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface XYChartData {
|
export interface XYChartData {
|
||||||
xAxis: AxisDataType;
|
xAxis: AxisDataType;
|
||||||
yAxis: AxisDataType;
|
yAxis: AxisDataType;
|
||||||
@@ -88,19 +58,6 @@ export interface Dimension {
|
|||||||
|
|
||||||
export interface BoundingRect extends Point, Dimension {}
|
export interface BoundingRect extends Point, Dimension {}
|
||||||
|
|
||||||
export interface XYChartSpaceProperty extends BoundingRect {
|
|
||||||
orientation: OrientationEnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface XYChartSpace {
|
|
||||||
chart: XYChartSpaceProperty;
|
|
||||||
title: XYChartSpaceProperty;
|
|
||||||
xAxisLabels: XYChartSpaceProperty;
|
|
||||||
xAxisTitle: XYChartSpaceProperty;
|
|
||||||
yAxisLabel: XYChartSpaceProperty;
|
|
||||||
yAxisTitle: XYChartSpaceProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Point {
|
export interface Point {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { DrawableElem, OrientationEnum, XYChartConfig, XYChartData } from './Interfaces.js';
|
import { DrawableElem, XYChartData } from './Interfaces.js';
|
||||||
import { getChartTitleComponent } from './components/ChartTitle.js';
|
import { getChartTitleComponent } from './components/ChartTitle.js';
|
||||||
import { ChartComponent } from './Interfaces.js';
|
import { ChartComponent } from './Interfaces.js';
|
||||||
import { IAxis, getAxis } from './components/axis/index.js';
|
import { IAxis, getAxis } from './components/axis/index.js';
|
||||||
import { IPlot, getPlotComponent } from './components/plot/index.js';
|
import { IPlot, getPlotComponent } from './components/plot/index.js';
|
||||||
|
import { XYChartConfig } from '../../../config.type.js';
|
||||||
|
|
||||||
export class Orchestrator {
|
export class Orchestrator {
|
||||||
private componentStore: {
|
private componentStore: {
|
||||||
@@ -158,7 +159,7 @@ export class Orchestrator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private calculateSpace() {
|
private calculateSpace() {
|
||||||
if (this.chartConfig.chartOrientation === OrientationEnum.HORIZONTAL) {
|
if (this.chartConfig.chartOrientation === 'horizontal') {
|
||||||
this.calculateHorizonatalSpace();
|
this.calculateHorizonatalSpace();
|
||||||
} else {
|
} else {
|
||||||
this.calculateVerticalSpace();
|
this.calculateVerticalSpace();
|
||||||
|
@@ -1,14 +1,13 @@
|
|||||||
import { ITextDimensionCalculator, TextDimensionCalculator } from '../TextDimensionCalculator.js';
|
import { ITextDimensionCalculator, TextDimensionCalculator } from '../TextDimensionCalculator.js';
|
||||||
import {
|
import {
|
||||||
XYChartConfig,
|
|
||||||
XYChartData,
|
XYChartData,
|
||||||
Dimension,
|
Dimension,
|
||||||
BoundingRect,
|
BoundingRect,
|
||||||
DrawableElem,
|
DrawableElem,
|
||||||
Point,
|
Point,
|
||||||
OrientationEnum,
|
|
||||||
} from '../Interfaces.js';
|
} from '../Interfaces.js';
|
||||||
import { ChartComponent } from '../Interfaces.js';
|
import { ChartComponent } from '../Interfaces.js';
|
||||||
|
import { XYChartConfig } from '../../../../config.type.js';
|
||||||
|
|
||||||
export class ChartTitle implements ChartComponent {
|
export class ChartTitle implements ChartComponent {
|
||||||
private boundingRect: BoundingRect;
|
private boundingRect: BoundingRect;
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
AxisConfig,
|
|
||||||
AxisDataType,
|
AxisDataType,
|
||||||
BandAxisDataType,
|
isBandAxisData,
|
||||||
LinearAxisDataType
|
|
||||||
} from '../../Interfaces.js';
|
} from '../../Interfaces.js';
|
||||||
import { TextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
import { TextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
||||||
import { ChartComponent } from '../../Interfaces.js';
|
import { ChartComponent } from '../../Interfaces.js';
|
||||||
import { BandAxis } from './BandAxis.js';
|
import { BandAxis } from './BandAxis.js';
|
||||||
import { LinearAxis } from './LinearAxis.js';
|
import { LinearAxis } from './LinearAxis.js';
|
||||||
|
import { XYChartAxisConfig } from '../../../../../config.type.js';
|
||||||
|
|
||||||
export type AxisPosition = 'left' | 'right' | 'top' | 'bottom';
|
export type AxisPosition = 'left' | 'right' | 'top' | 'bottom';
|
||||||
|
|
||||||
@@ -19,15 +18,7 @@ export interface IAxis extends ChartComponent {
|
|||||||
setRange(range: [number, number]): void;
|
setRange(range: [number, number]): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLinearAxisData(data: any): data is LinearAxisDataType {
|
export function getAxis(data: AxisDataType, axisConfig: XYChartAxisConfig): IAxis {
|
||||||
return !(Number.isNaN(data.min) || Number.isNaN(data.max));
|
|
||||||
}
|
|
||||||
|
|
||||||
function isBandAxisData(data: any): data is BandAxisDataType {
|
|
||||||
return data.categories && Array.isArray(data.categories);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAxis(data: AxisDataType, axisConfig: AxisConfig): IAxis {
|
|
||||||
const textDimansionCalculator = new TextDimensionCalculator();
|
const textDimansionCalculator = new TextDimensionCalculator();
|
||||||
if (isBandAxisData(data)) {
|
if (isBandAxisData(data)) {
|
||||||
return new BandAxis(axisConfig, data.categories, data.title, textDimansionCalculator);
|
return new BandAxis(axisConfig, data.categories, data.title, textDimansionCalculator);
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
|
import { XYChartConfig } from '../../../../../config.type.js';
|
||||||
import {
|
import {
|
||||||
BarPlotData,
|
BarPlotData,
|
||||||
BoundingRect,
|
BoundingRect,
|
||||||
DrawableElem,
|
DrawableElem,
|
||||||
OrientationEnum,
|
|
||||||
SimplePlotDataType,
|
|
||||||
} from '../../Interfaces.js';
|
} from '../../Interfaces.js';
|
||||||
import { IAxis } from '../axis/index.js';
|
import { IAxis } from '../axis/index.js';
|
||||||
|
|
||||||
@@ -13,7 +12,7 @@ export class BarPlot {
|
|||||||
private boundingRect: BoundingRect,
|
private boundingRect: BoundingRect,
|
||||||
private xAxis: IAxis,
|
private xAxis: IAxis,
|
||||||
private yAxis: IAxis,
|
private yAxis: IAxis,
|
||||||
private orientation: OrientationEnum
|
private orientation: XYChartConfig['chartOrientation']
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getDrawableElement(): DrawableElem[] {
|
getDrawableElement(): DrawableElem[] {
|
||||||
@@ -29,7 +28,7 @@ export class BarPlot {
|
|||||||
(1 - barPaddingPercent / 100);
|
(1 - barPaddingPercent / 100);
|
||||||
const barWidthHalf = barWidth / 2;
|
const barWidthHalf = barWidth / 2;
|
||||||
|
|
||||||
if (this.orientation === OrientationEnum.HORIZONTAL) {
|
if (this.orientation === 'horizontal') {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
groupTexts: ['plot', 'bar-plot'],
|
groupTexts: ['plot', 'bar-plot'],
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
import { line } from 'd3';
|
import { line } from 'd3';
|
||||||
import { DrawableElem, LinePlotData, OrientationEnum } from '../../Interfaces.js';
|
import { DrawableElem, LinePlotData } from '../../Interfaces.js';
|
||||||
import { IAxis } from '../axis/index.js';
|
import { IAxis } from '../axis/index.js';
|
||||||
|
import { XYChartConfig } from '../../../../../config.type.js';
|
||||||
|
|
||||||
export class LinePlot {
|
export class LinePlot {
|
||||||
constructor(
|
constructor(
|
||||||
private plotData: LinePlotData,
|
private plotData: LinePlotData,
|
||||||
private xAxis: IAxis,
|
private xAxis: IAxis,
|
||||||
private yAxis: IAxis,
|
private yAxis: IAxis,
|
||||||
private orientation: OrientationEnum
|
private orientation: XYChartConfig['chartOrientation']
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getDrawableElement(): DrawableElem[] {
|
getDrawableElement(): DrawableElem[] {
|
||||||
@@ -17,7 +18,7 @@ export class LinePlot {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
let path: string | null;
|
let path: string | null;
|
||||||
if (this.orientation === OrientationEnum.HORIZONTAL) {
|
if (this.orientation === 'horizontal') {
|
||||||
path = line()
|
path = line()
|
||||||
.y((d) => d[0])
|
.y((d) => d[0])
|
||||||
.x((d) => d[1])(finalData);
|
.x((d) => d[1])(finalData);
|
||||||
|
@@ -1,17 +1,20 @@
|
|||||||
import { BoundingRect, DrawableElem, OrientationEnum } from '../../Interfaces.js';
|
import { XYChartConfig } from '../../../../../config.type.js';
|
||||||
|
import { BoundingRect, DrawableElem } from '../../Interfaces.js';
|
||||||
export class PlotBorder {
|
export class PlotBorder {
|
||||||
constructor(private boundingRect: BoundingRect, private orientation: OrientationEnum) {}
|
constructor(private boundingRect: BoundingRect, private orientation: XYChartConfig['chartOrientation']) {}
|
||||||
|
|
||||||
getDrawableElement(): DrawableElem[] {
|
getDrawableElement(): DrawableElem[] {
|
||||||
const {x, y, width, height} = this.boundingRect;
|
const { x, y, width, height } = this.boundingRect;
|
||||||
if(this.orientation === OrientationEnum.HORIZONTAL) {
|
if (this.orientation === 'horizontal') {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
groupTexts: ['plot', 'chart-border'],
|
groupTexts: ['plot', 'chart-border'],
|
||||||
type: 'path',
|
type: 'path',
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
path: `M ${x},${y} L ${x + width},${y} M ${x + width},${y + height} M ${x},${y + height} L ${x},${y}`,
|
path: `M ${x},${y} L ${x + width},${y} M ${x + width},${y + height} M ${x},${
|
||||||
|
y + height
|
||||||
|
} L ${x},${y}`,
|
||||||
strokeFill: '#000000',
|
strokeFill: '#000000',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
},
|
},
|
||||||
@@ -25,7 +28,9 @@ export class PlotBorder {
|
|||||||
type: 'path',
|
type: 'path',
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
path: `M ${x},${y} M ${x + width},${y} M ${x + width},${y + height} L ${x},${y + height} L ${x},${y}`,
|
path: `M ${x},${y} M ${x + width},${y} M ${x + width},${y + height} L ${x},${
|
||||||
|
y + height
|
||||||
|
} L ${x},${y}`,
|
||||||
strokeFill: '#000000',
|
strokeFill: '#000000',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
},
|
},
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
XYChartConfig,
|
|
||||||
XYChartData,
|
XYChartData,
|
||||||
Dimension,
|
Dimension,
|
||||||
BoundingRect,
|
BoundingRect,
|
||||||
DrawableElem,
|
DrawableElem,
|
||||||
Point,
|
Point,
|
||||||
OrientationEnum,
|
|
||||||
ChartPlotEnum,
|
ChartPlotEnum,
|
||||||
} from '../../Interfaces.js';
|
} from '../../Interfaces.js';
|
||||||
import { IAxis } from '../axis/index.js';
|
import { IAxis } from '../axis/index.js';
|
||||||
@@ -13,6 +11,7 @@ import { ChartComponent } from '../../Interfaces.js';
|
|||||||
import { LinePlot } from './LinePlot.js';
|
import { LinePlot } from './LinePlot.js';
|
||||||
import { PlotBorder } from './PlotBorder.js';
|
import { PlotBorder } from './PlotBorder.js';
|
||||||
import { BarPlot } from './BarPlot.js';
|
import { BarPlot } from './BarPlot.js';
|
||||||
|
import { XYChartConfig } from '../../../../../config.type.js';
|
||||||
|
|
||||||
|
|
||||||
export interface IPlot extends ChartComponent {
|
export interface IPlot extends ChartComponent {
|
||||||
|
@@ -1,107 +1,18 @@
|
|||||||
// @ts-ignore: TODO Fix ts errors
|
// @ts-ignore: TODO Fix ts errors
|
||||||
import { defaultConfig } from '../../../config.js';
|
import { XYChartConfig } from '../../../config.type.js';
|
||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import {
|
import {
|
||||||
ChartPlotEnum,
|
|
||||||
DrawableElem,
|
DrawableElem,
|
||||||
OrientationEnum,
|
XYChartData,
|
||||||
XYChartConfig,
|
|
||||||
XYChartData
|
|
||||||
} from './Interfaces.js';
|
} from './Interfaces.js';
|
||||||
import { Orchestrator } from './Orchestrator.js';
|
import { Orchestrator } from './Orchestrator.js';
|
||||||
|
|
||||||
export class XYChartBuilder {
|
export class XYChartBuilder {
|
||||||
private config: XYChartConfig;
|
|
||||||
private chartData: XYChartData;
|
|
||||||
|
|
||||||
constructor() {
|
static build(config: XYChartConfig, chartData: XYChartData): DrawableElem[] {
|
||||||
this.config = {
|
log.trace(`Build start with Config: ${JSON.stringify(config, null, 2)}`);
|
||||||
width: 700,
|
log.trace(`Build start with ChartData: ${JSON.stringify(chartData, null, 2)}`);
|
||||||
height: 500,
|
const orchestrator = new Orchestrator(config, chartData);
|
||||||
fontFamily: defaultConfig.fontFamily || 'Sans',
|
|
||||||
titleFontSize: 16,
|
|
||||||
titleFill: '#000000',
|
|
||||||
titlePadding: 5,
|
|
||||||
showtitle: true,
|
|
||||||
plotBorderWidth: 2,
|
|
||||||
yAxis: {
|
|
||||||
showLabel: true,
|
|
||||||
labelFontSize: 14,
|
|
||||||
lablePadding: 5,
|
|
||||||
labelFill: '#000000',
|
|
||||||
showTitle: true,
|
|
||||||
titleFontSize: 16,
|
|
||||||
titlePadding: 5,
|
|
||||||
titleFill: '#000000',
|
|
||||||
showTick: true,
|
|
||||||
tickLength: 5,
|
|
||||||
tickWidth: 2,
|
|
||||||
tickFill: '#000000',
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
showLabel: true,
|
|
||||||
labelFontSize: 14,
|
|
||||||
lablePadding: 5,
|
|
||||||
labelFill: '#000000',
|
|
||||||
showTitle: true,
|
|
||||||
titleFontSize: 16,
|
|
||||||
titlePadding: 5,
|
|
||||||
titleFill: '#000000',
|
|
||||||
showTick: true,
|
|
||||||
tickLength: 5,
|
|
||||||
tickWidth: 2,
|
|
||||||
tickFill: '#000000',
|
|
||||||
},
|
|
||||||
chartOrientation: OrientationEnum.HORIZONTAL,
|
|
||||||
plotReservedSpacePercent: 50,
|
|
||||||
};
|
|
||||||
this.chartData = {
|
|
||||||
yAxis: {
|
|
||||||
title: 'yAxis1',
|
|
||||||
min: 0,
|
|
||||||
max: 100,
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
title: 'xAxis',
|
|
||||||
categories: ['category1', 'category2', 'category3'],
|
|
||||||
},
|
|
||||||
title: 'this is a sample task',
|
|
||||||
plots: [
|
|
||||||
{
|
|
||||||
type: ChartPlotEnum.BAR,
|
|
||||||
fill: '#0000bb',
|
|
||||||
data: [
|
|
||||||
['category1', 23],
|
|
||||||
['category2', 56],
|
|
||||||
['category3', 34],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: ChartPlotEnum.LINE,
|
|
||||||
strokeFill: '#bb0000',
|
|
||||||
strokeWidth: 2,
|
|
||||||
data: [
|
|
||||||
['category1', 33],
|
|
||||||
['category2', 45],
|
|
||||||
['category3', 65],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
setWidth(width: number) {
|
|
||||||
this.config.width = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
setHeight(height: number) {
|
|
||||||
this.config.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
build(): DrawableElem[] {
|
|
||||||
log.trace(`Build start with Config: ${JSON.stringify(this.config, null, 2)}`);
|
|
||||||
log.trace(`Build start with ChartData: ${JSON.stringify(this.chartData, null, 2)}`);
|
|
||||||
const orchestrator = new Orchestrator(this.config, this.chartData);
|
|
||||||
return orchestrator.getDrawableElement();
|
return orchestrator.getDrawableElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
%x axis_data
|
%x axis_data
|
||||||
%x axis_data_band
|
%x axis_data_band
|
||||||
%x axis_data_band_capture
|
%x axis_data_band_capture
|
||||||
%x axis_data_band_str
|
|
||||||
%x line
|
%x line
|
||||||
%x line_title
|
%x line_title
|
||||||
%x line_data
|
%x line_data
|
||||||
@@ -67,14 +66,10 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
|
|||||||
|
|
||||||
<axis_data>[+-]?\d+(?:\.\d+)?" "*"-->"" "*[+-]?\d+(?:\.\d+)?" "* { return 'AXIS_RANGE_DATA';}
|
<axis_data>[+-]?\d+(?:\.\d+)?" "*"-->"" "*[+-]?\d+(?:\.\d+)?" "* { return 'AXIS_RANGE_DATA';}
|
||||||
|
|
||||||
<axis_data>[\[]" "* {this.begin("axis_data_band"); this.begin("axis_data_band_capture")}
|
<axis_data>[\[]" "* {this.begin("axis_data_band"), this.begin("axis_data_band_capture")}
|
||||||
<axis_data_band>[,]" "* {this.begin("axis_data_band_capture")}
|
<axis_data_band_capture>(["][^",]+["]|[^\s\"\,]]+)" "*([,]" "*(["][^",]+["]|[^\s\]",]+)" "*)* { this.popState(); return "AXIS_BAND_DATA"; }
|
||||||
<axis_data_band_capture>["] {this.begin("axis_data_band_str");}
|
|
||||||
<axis_data_band_str>[^"]+ {return "AXIS_BAND_DATA";}
|
|
||||||
<axis_data_band_str>["]" "* {this.popState(); this.popState();}
|
|
||||||
<axis_data_band_capture>[^\s]+" "* {this.popState(); return "AXIS_BAND_DATA"}
|
|
||||||
<axis_data_band>[\]]" "* {this.popState(); return "AXIS_BAND_DATA_END"}
|
<axis_data_band>[\]]" "* {this.popState(); return "AXIS_BAND_DATA_END"}
|
||||||
<axis_data>[\r\n]+ {this.popState(); this.popState();}
|
<axis_data>[\s]+ {this.popState(); this.popState();}
|
||||||
|
|
||||||
|
|
||||||
"line"" "* {this.begin("line"); return 'LINE';}
|
"line"" "* {this.begin("line"); return 'LINE';}
|
||||||
@@ -162,27 +157,27 @@ statement
|
|||||||
;
|
;
|
||||||
|
|
||||||
parseLine
|
parseLine
|
||||||
: LINE LINE_TITLE LINE_DATA {yy.addLineData($2.trim(), $3.split(',').map(d => Number(d.trim())));}
|
: LINE LINE_TITLE LINE_DATA {yy.setLineData($2.trim(), $3.split(',').map(d => Number(d.trim())));}
|
||||||
;
|
;
|
||||||
|
|
||||||
parseBar
|
parseBar
|
||||||
: BAR BAR_TITLE BAR_DATA {yy.addBarData($2.trim(), $3.split(',').map(d => Number(d.trim())));}
|
: BAR BAR_TITLE BAR_DATA {yy.setBarData($2.trim(), $3.split(',').map(d => Number(d.trim())));}
|
||||||
;
|
;
|
||||||
|
|
||||||
parseXAxis
|
parseXAxis
|
||||||
: AXIS_TITLE statement {yy.setXAxisTitle($1.trim());}
|
: AXIS_TITLE statement {yy.setXAxisTitle($1.trim());}
|
||||||
| AXIS_TITLE xAxisBandData {yy.setXAxisTitle($1.trim());}
|
| AXIS_TITLE xAxisBandData statement {yy.setXAxisTitle($1.trim());}
|
||||||
| AXIS_TITLE AXIS_RANGE_DATA {yy.setXAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setXAxisRangeData(Number($$[0]), Number($$[1]));}
|
| AXIS_TITLE AXIS_RANGE_DATA statement {yy.setXAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setXAxisRangeData(Number($$[0]), Number($$[1]));}
|
||||||
;
|
;
|
||||||
|
|
||||||
xAxisBandData
|
xAxisBandData
|
||||||
: AXIS_BAND_DATA xAxisBandData {yy.addXAxisBand($1.trim());}
|
: AXIS_BAND_DATA xAxisBandData {yy.setXAxisBand($1.split(',').map(d => { let m = d.trim().match(/^(?:["]([^"]+)["]|([^\s"]+))$/); return m ? m[1] || m[2] : "";}));}
|
||||||
| AXIS_BAND_DATA_END
|
| AXIS_BAND_DATA_END
|
||||||
;
|
;
|
||||||
|
|
||||||
parseYAxis
|
parseYAxis
|
||||||
: AXIS_TITLE statement {yy.setYAxisTitle($1.trim());}
|
: AXIS_TITLE statement {yy.setYAxisTitle($1.trim());}
|
||||||
| AXIS_TITLE AXIS_RANGE_DATA {yy.setYAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setYAxisRangeData(Number($$[0]), Number($$[1]));}
|
| AXIS_TITLE AXIS_RANGE_DATA statement {yy.setYAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setYAxisRangeData(Number($$[0]), Number($$[1]));}
|
||||||
;
|
;
|
||||||
|
|
||||||
directive
|
directive
|
||||||
|
@@ -14,12 +14,11 @@ const mockDB: Record<string, Mock<any, any>> = {
|
|||||||
setDiagramTitle: vi.fn(),
|
setDiagramTitle: vi.fn(),
|
||||||
setXAxisTitle: vi.fn(),
|
setXAxisTitle: vi.fn(),
|
||||||
setXAxisRangeData: vi.fn(),
|
setXAxisRangeData: vi.fn(),
|
||||||
addXAxisBand: vi.fn(),
|
setXAxisBand: vi.fn(),
|
||||||
setYAxisTitle: vi.fn(),
|
setYAxisTitle: vi.fn(),
|
||||||
setYAxisRangeData: vi.fn(),
|
setYAxisRangeData: vi.fn(),
|
||||||
addYAxisBand: vi.fn(),
|
setLineData: vi.fn(),
|
||||||
addLineData: vi.fn(),
|
setBarData: vi.fn(),
|
||||||
addBarData: vi.fn(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function clearMocks() {
|
function clearMocks() {
|
||||||
@@ -109,12 +108,27 @@ describe('Testing xychart jison file', () => {
|
|||||||
|
|
||||||
clearMocks();
|
clearMocks();
|
||||||
|
|
||||||
str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2 ] \n';
|
str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2 ] \n ';
|
||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
expect(mockDB.addXAxisBand).toHaveBeenCalledTimes(2);
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith(["cat1", "cat2"]);
|
||||||
expect(mockDB.addXAxisBand).toHaveBeenNthCalledWith(1, 'cat2');
|
clearMocks();
|
||||||
expect(mockDB.addXAxisBand).toHaveBeenNthCalledWith(2, 'cat1');
|
|
||||||
|
|
||||||
|
str = `xychart-beta \n x-axis "this is x axis" [category1, "category 2", category3]\n`
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('this is x axis');
|
||||||
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith(["category1", "category 2", "category3"]);
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta \nx-axis xAxisName [ "cat1 with space" , cat2 , cat3] \n ';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith(["cat1 with space", "cat2", "cat3"]);
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta \nx-axis xAxisName [ "cat1 with space" , cat2 asdf , cat3] \n ';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
});
|
});
|
||||||
it('parse y-axis', () => {
|
it('parse y-axis', () => {
|
||||||
let str = 'xychart-beta \ny-axis yAxisName\n';
|
let str = 'xychart-beta \ny-axis yAxisName\n';
|
||||||
@@ -150,7 +164,7 @@ describe('Testing xychart jison file', () => {
|
|||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
expect(mockDB.addLineData).toHaveBeenCalledWith('lineTitle', [23, 45, 56.6]);
|
expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle', [23, 45, 56.6]);
|
||||||
|
|
||||||
clearMocks();
|
clearMocks();
|
||||||
|
|
||||||
@@ -159,7 +173,7 @@ describe('Testing xychart jison file', () => {
|
|||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
expect(mockDB.addLineData).toHaveBeenCalledWith('lineTitle with space', [23, -45, 56.6]);
|
expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle with space', [23, -45, 56.6]);
|
||||||
|
|
||||||
clearMocks();
|
clearMocks();
|
||||||
str =
|
str =
|
||||||
@@ -171,7 +185,7 @@ describe('Testing xychart jison file', () => {
|
|||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
expect(mockDB.addBarData).toHaveBeenCalledWith('barTitle', [23, 45, 56.6]);
|
expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle', [23, 45, 56.6]);
|
||||||
|
|
||||||
clearMocks();
|
clearMocks();
|
||||||
|
|
||||||
@@ -180,7 +194,7 @@ describe('Testing xychart jison file', () => {
|
|||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
expect(mockDB.addBarData).toHaveBeenCalledWith('barTitle with space', [23, -45, 56.6]);
|
expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle with space', [23, -45, 56.6]);
|
||||||
clearMocks();
|
clearMocks();
|
||||||
|
|
||||||
str =
|
str =
|
||||||
@@ -193,9 +207,29 @@ describe('Testing xychart jison file', () => {
|
|||||||
expect(parserFnConstructor(str)).not.toThrow();
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
||||||
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
expect(mockDB.addBarData).toHaveBeenCalledWith('barTitle1', [23, 45, 56.6]);
|
expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle1', [23, 45, 56.6]);
|
||||||
expect(mockDB.addBarData).toHaveBeenCalledWith('barTitle2', [13, 42, 56.89]);
|
expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle2', [13, 42, 56.89]);
|
||||||
expect(mockDB.addLineData).toHaveBeenCalledWith('lineTitle1', [11, 45.5, 67, 23]);
|
expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle1', [11, 45.5, 67, 23]);
|
||||||
expect(mockDB.addLineData).toHaveBeenCalledWith('lineTitle2', [45, 99, 12]);
|
expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle2', [45, 99, 12]);
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = `
|
||||||
|
xychart-beta horizontal
|
||||||
|
title Basic xychart
|
||||||
|
x-axis "this is x axis" [category1, "category 2", category3]
|
||||||
|
y-axis yaxisText 10 --> 150
|
||||||
|
bar barTitle1 [23, 45, 56.6]
|
||||||
|
line lineTitle1 [11, 45.5, 67, 23]
|
||||||
|
bar barTitle2 [13, 42, 56.89]
|
||||||
|
line lineTitle2 [45, 99, 012]`;
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yaxisText');
|
||||||
|
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(10, 150);
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('this is x axis');
|
||||||
|
expect(mockDB.setXAxisBand).toHaveBeenCalledWith(["category1", "category 2", "category3"]);
|
||||||
|
expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle1', [23, 45, 56.6]);
|
||||||
|
expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle2', [13, 42, 56.89]);
|
||||||
|
expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle1', [11, 45.5, 67, 23]);
|
||||||
|
expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle2', [45, 99, 12]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -12,9 +12,96 @@ import {
|
|||||||
clear as commonClear,
|
clear as commonClear,
|
||||||
} from '../../commonDb.js';
|
} from '../../commonDb.js';
|
||||||
import { XYChartBuilder } from './chartBuilder/index.js';
|
import { XYChartBuilder } from './chartBuilder/index.js';
|
||||||
import { DrawableElem } from './chartBuilder/Interfaces.js';
|
import { ChartPlotEnum, DrawableElem, XYChartData, isBandAxisData } from './chartBuilder/Interfaces.js';
|
||||||
|
import { XYChartConfig } from '../../config.type.js';
|
||||||
|
|
||||||
const config = configApi.getConfig();
|
const config = configApi.getConfig();
|
||||||
|
let chartWidth = 600;
|
||||||
|
let chartHeight = 500;
|
||||||
|
|
||||||
|
function getChartDefaultConfig(): XYChartConfig {
|
||||||
|
return config.xyChart
|
||||||
|
? { ...config.xyChart, yAxis: { ...config.xyChart.yAxis }, xAxis: { ...config.xyChart.xAxis } }
|
||||||
|
: {
|
||||||
|
width: 700,
|
||||||
|
height: 500,
|
||||||
|
fontFamily: config.fontFamily || 'Sans',
|
||||||
|
titleFontSize: 16,
|
||||||
|
titleFill: '#000000',
|
||||||
|
titlePadding: 5,
|
||||||
|
showtitle: true,
|
||||||
|
plotBorderWidth: 2,
|
||||||
|
yAxis: {
|
||||||
|
showLabel: true,
|
||||||
|
labelFontSize: 14,
|
||||||
|
lablePadding: 5,
|
||||||
|
labelFill: '#000000',
|
||||||
|
showTitle: true,
|
||||||
|
titleFontSize: 16,
|
||||||
|
titlePadding: 5,
|
||||||
|
titleFill: '#000000',
|
||||||
|
showTick: true,
|
||||||
|
tickLength: 5,
|
||||||
|
tickWidth: 2,
|
||||||
|
tickFill: '#000000',
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
showLabel: true,
|
||||||
|
labelFontSize: 14,
|
||||||
|
lablePadding: 5,
|
||||||
|
labelFill: '#000000',
|
||||||
|
showTitle: true,
|
||||||
|
titleFontSize: 16,
|
||||||
|
titlePadding: 5,
|
||||||
|
titleFill: '#000000',
|
||||||
|
showTick: true,
|
||||||
|
tickLength: 5,
|
||||||
|
tickWidth: 2,
|
||||||
|
tickFill: '#000000',
|
||||||
|
},
|
||||||
|
chartOrientation: 'vertical',
|
||||||
|
plotReservedSpacePercent: 50,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChartDefalutData(): XYChartData {
|
||||||
|
return {
|
||||||
|
yAxis: {
|
||||||
|
title: 'yAxis1',
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
title: 'xAxis',
|
||||||
|
categories: [],
|
||||||
|
},
|
||||||
|
title: '',
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
type: ChartPlotEnum.BAR,
|
||||||
|
fill: '#0000bb',
|
||||||
|
data: [
|
||||||
|
['category1', 23],
|
||||||
|
['category 2', 56],
|
||||||
|
['category3', 34],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: ChartPlotEnum.LINE,
|
||||||
|
strokeFill: '#bb0000',
|
||||||
|
strokeWidth: 2,
|
||||||
|
data: [
|
||||||
|
['category1', 33],
|
||||||
|
['category 2', 45],
|
||||||
|
['category3', 65],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let xyChartConfig: XYChartConfig = getChartDefaultConfig();
|
||||||
|
let xyChartData: XYChartData = getChartDefalutData();
|
||||||
|
|
||||||
function textSanitizer(text: string) {
|
function textSanitizer(text: string) {
|
||||||
return sanitizeText(text.trim(), config);
|
return sanitizeText(text.trim(), config);
|
||||||
@@ -23,24 +110,51 @@ function textSanitizer(text: string) {
|
|||||||
function parseDirective(statement: string, context: string, type: string) {
|
function parseDirective(statement: string, context: string, type: string) {
|
||||||
// @ts-ignore: TODO Fix ts errors
|
// @ts-ignore: TODO Fix ts errors
|
||||||
mermaidAPI.parseDirective(this, statement, context, type);
|
mermaidAPI.parseDirective(this, statement, context, type);
|
||||||
};
|
}
|
||||||
|
|
||||||
const xyChartBuilder = new XYChartBuilder();
|
|
||||||
|
function setOrientation(oriantation: string) {
|
||||||
|
if (oriantation === 'horizontal') {
|
||||||
|
xyChartConfig.chartOrientation = 'horizontal';
|
||||||
|
} else {
|
||||||
|
xyChartConfig.chartOrientation = 'vertical';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setXAxisTitle(title: string) {
|
||||||
|
xyChartData.xAxis.title = textSanitizer(title);
|
||||||
|
}
|
||||||
|
function setXAxisRangeData(min: number, max: number) {
|
||||||
|
xyChartData.xAxis = {title: xyChartData.xAxis.title, min, max};
|
||||||
|
}
|
||||||
|
function setXAxisBand(categories: string[]) {
|
||||||
|
xyChartData.xAxis = {title: xyChartData.xAxis.title, categories: categories.map(c => textSanitizer(c))};
|
||||||
|
}
|
||||||
|
function setYAxisTitle(title: string) {
|
||||||
|
xyChartData.yAxis.title = textSanitizer(title);
|
||||||
|
}
|
||||||
|
function setYAxisRangeData(min: number, max: number) {
|
||||||
|
xyChartData.yAxis = {title: xyChartData.yAxis.title, min, max};
|
||||||
|
}
|
||||||
|
function setLineData(title: string, data: number[]) {}
|
||||||
|
function setBarData(title: string, data: number[]) {}
|
||||||
|
|
||||||
function getDrawableElem(): DrawableElem[] {
|
function getDrawableElem(): DrawableElem[] {
|
||||||
return xyChartBuilder.build();
|
xyChartData.title = getDiagramTitle();
|
||||||
|
return XYChartBuilder.build(xyChartConfig, xyChartData);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setHeight(height: number) {
|
function setHeight(height: number) {
|
||||||
xyChartBuilder.setHeight(height);
|
xyChartConfig.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWidth(width: number) {
|
function setWidth(width: number) {
|
||||||
xyChartBuilder.setWidth(width);
|
xyChartConfig.width = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
const clear = function () {
|
const clear = function () {
|
||||||
commonClear();
|
commonClear();
|
||||||
|
xyChartConfig = getChartDefaultConfig();
|
||||||
|
xyChartData = getChartDefalutData();
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -55,4 +169,12 @@ export default {
|
|||||||
getDiagramTitle,
|
getDiagramTitle,
|
||||||
getAccDescription,
|
getAccDescription,
|
||||||
setAccDescription,
|
setAccDescription,
|
||||||
|
setOrientation,
|
||||||
|
setXAxisTitle,
|
||||||
|
setXAxisRangeData,
|
||||||
|
setXAxisBand,
|
||||||
|
setYAxisTitle,
|
||||||
|
setYAxisRangeData,
|
||||||
|
setLineData,
|
||||||
|
setBarData,
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user