impr: modify some apis

This commit is contained in:
liihuu 2024-09-03 23:46:32 +08:00
parent b25f15df81
commit 5be280359d
22 changed files with 281 additions and 472 deletions

View File

@ -1,3 +1,5 @@
import child_process from 'child_process'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import eslint from '@rollup/plugin-eslint'
import replace from '@rollup/plugin-replace'
@ -10,6 +12,7 @@ import progress from 'rollup-plugin-progress'
import { resolvePath, getVersion } from './utils.js'
const version = getVersion()
const commitId = child_process.execSync('git rev-parse --short HEAD').toString().trim()
const env = process.env.NODE_ENV
@ -33,7 +36,7 @@ function createInputConfig ({ input, replaceValues }) {
replace({
preventAssignment: true,
values: {
'__VERSION__': version,
'__VERSION__': `v${version}(${commitId})`,
...replaceValues
}
}),

View File

@ -22,7 +22,6 @@ import { UpdateLevel } from './common/Updater'
import { type Styles } from './common/Styles'
import type Crosshair from './common/Crosshair'
import { ActionType, type ActionCallback } from './common/Action'
import type LoadMoreCallback from './common/LoadMoreCallback'
import type LoadDataCallback from './common/LoadDataCallback'
import type Precision from './common/Precision'
import type VisibleRange from './common/VisibleRange'
@ -51,8 +50,8 @@ import { type PaneOptions, PanePosition, PANE_DEFAULT_HEIGHT, PaneIdConstants }
import type AxisImp from './component/Axis'
import { AxisPosition, type Axis } from './component/Axis'
import { type Indicator, type IndicatorCreate } from './component/Indicator'
import { type Overlay, type OverlayCreate, type OverlayRemove } from './component/Overlay'
import { type IndicatorFilter, type Indicator, type IndicatorCreate } from './component/Indicator'
import { type OverlayFilter, type Overlay, type OverlayCreate } from './component/Overlay'
import { getIndicatorClass } from './extension/indicator/index'
@ -94,27 +93,17 @@ export interface Chart {
getVisibleRange: () => VisibleRange
clearData: () => void
getDataList: () => KLineData[]
applyNewData: (dataList: KLineData[], more?: boolean, callback?: () => void) => void
/**
* @deprecated
* Since v9.8.0 deprecated, since v10 removed
*/
applyMoreData: (dataList: KLineData[], more?: boolean, callback?: () => void) => void
updateData: (data: KLineData, callback?: () => void) => void
/**
* @deprecated
* Since v9.8.0 deprecated, since v10 removed
*/
loadMore: (cb: LoadMoreCallback) => void
applyNewData: (dataList: KLineData[], more?: boolean) => void
updateData: (data: KLineData) => void
setLoadDataCallback: (cb: LoadDataCallback) => void
createIndicator: (value: string | IndicatorCreate, isStack?: boolean, paneOptions?: PaneOptions, callback?: () => void) => Nullable<string>
overrideIndicator: (override: IndicatorCreate, paneId?: string, callback?: () => void) => void
getIndicatorByPaneId: (paneId?: string, name?: string) => Nullable<Indicator> | Nullable<Map<string, Indicator>> | Map<string, Map<string, Indicator>>
removeIndicator: (paneId: string, name?: string) => void
createOverlay: (value: string | OverlayCreate | Array<string | OverlayCreate>, paneId?: string) => Nullable<string> | Array<Nullable<string>>
getOverlayById: (id: string) => Nullable<Overlay>
createIndicator: (value: string | IndicatorCreate, isStack?: boolean, paneOptions?: PaneOptions) => Nullable<string>
overrideIndicator: (override: IndicatorCreate) => void
getIndicators: (filter?: IndicatorFilter) => Map<string, Indicator[]>
removeIndicator: (filter?: IndicatorFilter) => void
createOverlay: (value: string | OverlayCreate | Array<string | OverlayCreate>) => Nullable<string> | Array<Nullable<string>>
getOverlays: (filter?: OverlayFilter) => Map<string, Overlay[]>
overrideOverlay: (override: Partial<OverlayCreate>) => void
removeOverlay: (remove?: string | OverlayRemove) => void
removeOverlay: (filter?: OverlayFilter) => void
setPaneOptions: (options: PaneOptions) => void
setZoomEnabled: (enabled: boolean) => void
isZoomEnabled: () => boolean
@ -405,11 +394,12 @@ export default class ChartImp implements Chart {
}
private _setPaneOptions (options: PaneOptions, forceShouldAdjust: boolean): void {
if (isString(options.id)) {
const pane = this.getDrawPaneById(options.id)
let shouldMeasureHeight = false
if (pane !== null) {
let shouldAdjust = forceShouldAdjust
let shouldMeasureHeight = false
let shouldAdjust = forceShouldAdjust
for (const pane of this._drawPanes) {
const paneIdValid = isValid(options.id)
const isSpecify = paneIdValid && pane.getId() === options.id
if (isSpecify || !paneIdValid) {
if (options.id !== PaneIdConstants.CANDLE && isNumber(options.height) && options.height > 0) {
const minHeight = Math.max(options.minHeight ?? pane.getOptions().minHeight, 0)
const height = Math.max(minHeight, options.height)
@ -417,15 +407,18 @@ export default class ChartImp implements Chart {
shouldAdjust = true
shouldMeasureHeight = true
}
if (isString(options.axis)) {
if (isValid(options.axis)) {
shouldAdjust = true
}
pane.setOptions(options)
if (shouldAdjust) {
this.adjustPaneViewport(shouldMeasureHeight, true, true, true, true)
if (isSpecify) {
break
}
}
}
if (shouldAdjust) {
this.adjustPaneViewport(shouldMeasureHeight, true, true, true, true)
}
}
getDrawPaneById (paneId: string): Nullable<DrawPane<Axis>> {
@ -500,7 +493,7 @@ export default class ChartImp implements Chart {
this._drawPanes.forEach(pane => {
const id = pane.getId()
const paneIndicatorData = {}
const indicators = this._chartStore.getIndicatorStore().getInstances(id)
const indicators = this._chartStore.getIndicatorStore().getInstanceByPaneId(id)
indicators.forEach(indicator => {
const result = indicator.result
paneIndicatorData[indicator.name] = result[crosshair.dataIndex ?? result.length - 1]
@ -671,46 +664,19 @@ export default class ChartImp implements Chart {
return this._chartStore.getDataList()
}
applyNewData (data: KLineData[], more?: boolean, callback?: () => void): void {
if (isValid(callback)) {
logWarn('applyNewData', '', 'param `callback` has been deprecated since version 9.8.0, use `subscribeAction(\'onDataReady\')` instead.')
}
applyNewData (data: KLineData[], more?: boolean): void {
this._chartStore.addData(data, LoadDataType.Init, more)
callback?.()
}
/**
* @deprecated
* Since v9.8.0 deprecated, since v10 removed
*/
applyMoreData (data: KLineData[], more?: boolean, callback?: () => void): void {
logWarn('', '', 'Api `applyMoreData` has been deprecated since version 9.8.0.')
this._chartStore.addData(data, LoadDataType.Forward, more ?? true)
callback?.()
}
updateData (data: KLineData, callback?: () => void): void {
if (isValid(callback)) {
logWarn('updateData', '', 'param `callback` has been deprecated since version 9.8.0, use `subscribeAction(\'onDataReady\')` instead.')
}
updateData (data: KLineData): void {
this._chartStore.addData(data)
callback?.()
}
/**
* @deprecated
* Since v9.8.0 deprecated, since v10 removed
*/
loadMore (cb: LoadMoreCallback): void {
logWarn('', '', 'Api `loadMore` has been deprecated since version 9.8.0, use `setLoadDataCallback` instead.')
this._chartStore.setLoadMoreCallback(cb)
}
setLoadDataCallback (cb: LoadDataCallback): void {
this._chartStore.setLoadDataCallback(cb)
}
createIndicator (value: string | IndicatorCreate, isStack?: boolean, paneOptions?: Nullable<PaneOptions>, callback?: () => void): Nullable<string> {
createIndicator (value: string | IndicatorCreate, isStack?: boolean, paneOptions?: Nullable<PaneOptions>): Nullable<string> {
const indicator = isString(value) ? { name: value } : value
if (getIndicatorClass(indicator.name) === null) {
logWarn('createIndicator', 'value', 'indicator not supported, you may need to use registerIndicator to add one!!!')
@ -732,40 +698,46 @@ export default class ChartImp implements Chart {
const result = this._chartStore.getIndicatorStore().addInstance(indicator, paneId, isStack ?? false)
if (result) {
this.adjustPaneViewport(true, true, true, true, true)
callback?.()
}
}
return paneId ?? null
}
overrideIndicator (override: IndicatorCreate, paneId?: Nullable<string>, callback?: () => void): void {
const result = this._chartStore.getIndicatorStore().override(override, paneId ?? null)
overrideIndicator (override: IndicatorCreate): void {
const result = this._chartStore.getIndicatorStore().override(override)
if (result) {
this.adjustPaneViewport(false, false, true)
callback?.()
}
}
getIndicatorByPaneId (paneId?: string, name?: string): Nullable<Indicator> | Nullable<Map<string, Indicator>> | Map<string, Map<string, Indicator>> {
return this._chartStore.getIndicatorStore().getInstanceByPaneId(paneId, name)
getIndicators (filter?: IndicatorFilter): Map<string, Indicator[]> {
return this._chartStore.getIndicatorStore().getInstanceByFilter(filter ?? {})
}
removeIndicator (paneId: string, name?: string): void {
removeIndicator (filter?: IndicatorFilter): void {
const indicatorStore = this._chartStore.getIndicatorStore()
const removed = indicatorStore.removeInstance(paneId, name)
const removed = indicatorStore.removeInstance(filter ?? {})
if (removed) {
let shouldMeasureHeight = false
if (paneId !== PaneIdConstants.CANDLE) {
const paneIds: string[] = []
this._drawPanes.forEach(pane => {
const paneId = pane.getId()
if (paneId !== PaneIdConstants.CANDLE && paneId !== PaneIdConstants.X_AXIS) {
paneIds.push(paneId)
}
})
paneIds.forEach(paneId => {
if (!indicatorStore.hasInstances(paneId)) {
const pane = this.getDrawPaneById(paneId)
const index = this._drawPanes.findIndex(p => p.getId() === paneId)
if (pane !== null) {
const index = this._drawPanes.findIndex(pane => pane.getId() === paneId)
const pane = this._drawPanes[index]
if (isValid(pane)) {
shouldMeasureHeight = true
const separatorPane = this._separatorPanes.get(pane)
if (isValid(separatorPane)) {
const topPane = separatorPane?.getTopPane()
for (const item of this._separatorPanes) {
if (item[1].getTopPane().getId() === pane.getId()) {
if (item[1].getTopPane().getId() === paneId) {
item[1].setTopPane(topPane)
break
}
@ -786,56 +758,57 @@ export default class ChartImp implements Chart {
this._separatorPanes.delete(firstPane)
}
}
}
})
this.adjustPaneViewport(shouldMeasureHeight, true, true, true, true)
}
}
createOverlay (value: string | OverlayCreate | Array<string | OverlayCreate>, paneId?: string): Nullable<string> | Array<Nullable<string>> {
let overlays: OverlayCreate[] = []
createOverlay (value: string | OverlayCreate | Array<string | OverlayCreate>): Nullable<string> | Array<Nullable<string>> {
const overlays: OverlayCreate[] = []
const appointPaneFlags: boolean[] = []
const build: ((overlay: OverlayCreate) => void) = overlay => {
if (!isValid(overlay.paneId) || this.getDrawPaneById(overlay.paneId) === null) {
overlay.paneId = PaneIdConstants.CANDLE
appointPaneFlags.push(false)
} else {
appointPaneFlags.push(true)
}
overlays.push(overlay)
}
if (isString(value)) {
overlays = [{ name: value }]
build({ name: value })
} else if (isArray<Array<string | OverlayCreate>>(value)) {
overlays = (value as Array<string | OverlayCreate>).map((v: string | OverlayCreate) => {
(value as Array<string | OverlayCreate>).forEach(v => {
let overlay: OverlayCreate
if (isString(v)) {
return { name: v }
overlay = { name: v }
} else {
overlay = v
}
return v
build(overlay)
})
} else {
const overlay = value as OverlayCreate
overlays = [overlay]
build(value as OverlayCreate)
}
let appointPaneFlag = true
if (!isValid(paneId) || this.getDrawPaneById(paneId) === null) {
paneId = PaneIdConstants.CANDLE
appointPaneFlag = false
}
const ids = this._chartStore.getOverlayStore().addInstances(overlays, paneId, appointPaneFlag)
const ids = this._chartStore.getOverlayStore().addInstances(overlays, appointPaneFlags)
if (isArray(value)) {
return ids
}
return ids[0]
}
getOverlayById (id: string): Nullable<Overlay> {
return this._chartStore.getOverlayStore().getInstanceById(id) ?? null
getOverlays (filter?: OverlayFilter): Map<string, Overlay[]> {
return this._chartStore.getOverlayStore().getInstanceByFilter(filter ?? {})
}
overrideOverlay (override: Partial<OverlayCreate>): void {
this._chartStore.getOverlayStore().override(override)
}
removeOverlay (remove?: string | OverlayRemove): void {
let overlayRemove: OverlayRemove
if (isValid(remove)) {
if (isString(remove)) {
overlayRemove = { id: remove }
} else {
overlayRemove = remove
}
}
this._chartStore.getOverlayStore().removeInstance(overlayRemove!)
removeOverlay (filter?: OverlayFilter): void {
this._chartStore.getOverlayStore().removeInstance(filter ?? {})
}
setPaneOptions (options: PaneOptions): void {

View File

@ -1,23 +0,0 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type Nullable from './Nullable'
/**
* Since v9.8.0 deprecated, since v10 removed
* @deprecated
*/
type LoadMoreCallback = (timestamp: Nullable<number>) => void
export default LoadMoreCallback

View File

@ -92,22 +92,10 @@ export interface TextStyle extends Padding {
backgroundColor: string | CanvasGradient
}
/**
* @deprecated
* Starting from v10, it will be deleted
*/
export type RectTextStyle = TextStyle
export interface StateTextStyle extends TextStyle {
show: boolean
}
/**
* @deprecated
* Starting from v10, it will be deleted
*/
export type StateRectTextStyle = StateTextStyle
export type LastValueMarkTextStyle = Omit<StateTextStyle, 'backgroundColor'>
export enum TooltipShowRule {
@ -145,23 +133,11 @@ export interface TooltipLegendChild {
color: string
}
/**
* @deprecated
* Starting from v10, it will be deleted
*/
export type TooltipDataChild = TooltipLegendChild
export interface TooltipLegend {
title: string | TooltipLegendChild
value: string | TooltipLegendChild
}
/**
* @deprecated
* Starting from v10, it will be deleted
*/
export type TooltipData = TooltipLegend
export enum TooltipIconPosition {
Left = 'left',
Middle = 'middle',
@ -349,11 +325,6 @@ export interface OverlayStyle {
circle: PolygonStyle
arc: LineStyle
text: TextStyle
/**
* @deprecated
* Starting from v10, it will be deleted
*/
rectText: TextStyle
[key: string]: any
}
@ -753,8 +724,7 @@ function getDefaultOverlayStyle (): OverlayStyle {
size: 1,
dashedValue: [2, 2]
},
text: text(),
rectText: text()
text: text()
}
}

View File

@ -85,7 +85,7 @@ export interface IndicatorTooltipData {
name: string
calcParamsText: string
icons: TooltipIconStyle[]
values: TooltipLegend[]
legends: TooltipLegend[]
}
export interface IndicatorCreateTooltipDataSourceParams<D> {
@ -221,7 +221,9 @@ export interface Indicator<D = any> {
export type IndicatorTemplate<D = any> = ExcludePickPartial<Omit<Indicator<D>, 'result'>, 'name' | 'calc'>
export type IndicatorCreate<D = any> = ExcludePickPartial<Omit<Indicator<D>, 'result'>, 'name'>
export type IndicatorCreate<D = any> = ExcludePickPartial<Omit<Indicator<D>, 'result'>, 'name'> & { paneId?: string }
export type IndicatorFilter = Partial<Pick<Indicator, 'name'>> & { paneId?: string }
export type IndicatorConstructor<D = any> = new () => IndicatorImp<D>

View File

@ -284,7 +284,7 @@ export interface Overlay {
export type OverlayTemplate = ExcludePickPartial<Omit<Overlay, 'id' | 'groupId' | 'paneId' | 'points' | 'currentStep'>, 'name'>
export type OverlayCreate = ExcludePickPartial<Omit<Overlay, 'currentStep' | 'totalStep' | 'createPointFigures' | 'createXAxisFigures' | 'createYAxisFigures' | 'performEventPressedMove' | 'performEventMoveForDrawing'>, 'name'>
export type OverlayRemove = Partial<Pick<Overlay, 'id' | 'groupId' | 'name'>>
export type OverlayFilter = Partial<Pick<Overlay, 'id' | 'groupId' | 'name' | 'paneId'>>
export type OverlayInnerConstructor = new () => OverlayImp
export type OverlayConstructor = new () => Overlay

View File

@ -32,7 +32,7 @@ import { PaneIdConstants } from '../pane/types'
export type YAxisTemplate = AxisTemplate
const TICK_COUNT = 10
const TICK_COUNT = 8
export interface YAxis extends Axis, YAxisTemplate {
isFromZero: () => boolean
@ -109,7 +109,7 @@ export default abstract class YAxisImp extends AxisImp implements YAxis {
let specifyMin = Number.MAX_SAFE_INTEGER
let specifyMax = Number.MIN_SAFE_INTEGER
let indicatorPrecision = Number.MAX_SAFE_INTEGER
const indicators = chartStore.getIndicatorStore().getInstances(parent.getId())
const indicators = chartStore.getIndicatorStore().getInstanceByPaneId(parent.getId())
indicators.forEach(indicator => {
if (!shouldOhlc) {
shouldOhlc = indicator.shouldOhlc ?? false
@ -287,7 +287,7 @@ export default abstract class YAxisImp extends AxisImp implements YAxis {
const chartStore = pane.getChart().getChartStore()
const customApi = chartStore.getCustomApi()
const optimalTicks: AxisTick[] = []
const indicators = chartStore.getIndicatorStore().getInstances(pane.getId())
const indicators = chartStore.getIndicatorStore().getInstanceByPaneId(pane.getId())
const thousandsSeparator = chartStore.getThousandsSeparator()
const decimalFoldThreshold = chartStore.getDecimalFoldThreshold()
let precision = 0
@ -362,7 +362,7 @@ export default abstract class YAxisImp extends AxisImp implements YAxis {
crosshairStyles.horizontal.show &&
crosshairStyles.horizontal.text.show
) {
const indicators = chartStore.getIndicatorStore().getInstances(pane.getId())
const indicators = chartStore.getIndicatorStore().getInstanceByPaneId(pane.getId())
let indicatorPrecision = 0
let shouldFormatBigNumber = false
indicators.forEach(indicator => {

View File

@ -21,12 +21,11 @@ import line from './line'
import polygon from './polygon'
import rect from './rect'
import text from './text'
import rectText from './rectText'
import arc from './arc'
const figures: Record<string, FigureInnerConstructor> = {}
const extensions = [circle, line, polygon, rect, text, rectText, arc]
const extensions = [circle, line, polygon, rect, text, arc]
extensions.forEach((figure: FigureTemplate) => {
figures[figure.name] = FigureImp.extend(figure)
})

View File

@ -1,37 +0,0 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import text, { drawText } from './text'
/**
* @deprecated
* Starting from v10, it will be deleted
*/
const rectText = text
/**
* @deprecated
* Starting from v10, it will be deleted
*/
const drawRectText = drawText
/**
* @deprecated
* Starting from v10, it will be deleted
*/
export {
drawRectText
}
export default rectText

View File

@ -52,7 +52,6 @@ import {
} from './extension/figure/line'
import { checkCoordinateOnPolygon, drawPolygon } from './extension/figure/polygon'
import { checkCoordinateOnRect, drawRect } from './extension/figure/rect'
import { drawRectText } from './extension/figure/rectText'
import { checkCoordinateOnText, drawText } from './extension/figure/text'
import { registerFigure, getSupportedFigures, getFigureClass } from './extension/figure/index'
@ -159,8 +158,7 @@ const utils = {
drawLine,
drawPolygon,
drawRect,
drawText,
drawRectText
drawText
}
export {

View File

@ -14,11 +14,6 @@
import { type AxisCreate } from '../component/Axis'
export interface PaneGap {
top?: number
bottom?: number
}
export const enum PanePosition {
Top = 'top',
Bottom = 'bottom'

View File

@ -21,7 +21,6 @@ import { getDefaultStyles, type Styles, type TooltipLegend } from '../common/Sty
import { isArray, isNumber, isString, isValid, merge } from '../common/utils/typeChecks'
import type LoadDataCallback from '../common/LoadDataCallback'
import { type LoadDataParams, LoadDataType } from '../common/LoadDataCallback'
import type LoadMoreCallback from '../common/LoadMoreCallback'
import { ActionType } from '../common/Action'
import { getDefaultCustomApi, type CustomApi, defaultLocale, type Options } from '../Options'
@ -74,13 +73,6 @@ export default class ChartStore {
*/
private _dataList: KLineData[] = []
/**
* Load more data callback
* Since v9.8.0 deprecated, since v10 removed
* @deprecated
*/
private _loadMoreCallback: Nullable<LoadMoreCallback> = null
/**
* Load data callback
*/
@ -290,24 +282,13 @@ export default class ChartStore {
if (adjustFlag) {
this._timeScaleStore.adjustVisibleRange()
this._tooltipStore.recalculateCrosshair(true)
this._indicatorStore.calcInstance()
this._indicatorStore.calcInstance({})
this._chart.adjustPaneViewport(false, true, true, true)
}
this._actionStore.execute(ActionType.OnDataReady)
}
}
setLoadMoreCallback (callback: LoadMoreCallback): void {
this._loadMoreCallback = callback
}
executeLoadMoreCallback (timestamp: Nullable<number>): void {
if (this._forwardMore && !this._loading && isValid(this._loadMoreCallback)) {
this._loading = true
this._loadMoreCallback(timestamp)
}
}
setLoadDataCallback (callback: LoadDataCallback): void {
this._loadDataCallback = callback
}

View File

@ -12,12 +12,11 @@
* limitations under the License.
*/
import type Nullable from '../common/Nullable'
import { isValid, isString } from '../common/utils/typeChecks'
import type ChartStore from './ChartStore'
import { type IndicatorCreate, type Indicator } from '../component/Indicator'
import { type IndicatorCreate, type IndicatorFilter } from '../component/Indicator'
import type IndicatorImp from '../component/Indicator'
import { IndicatorSeries } from '../component/Indicator'
import { getIndicatorClass } from '../extension/indicator/index'
@ -74,7 +73,7 @@ export default class IndicatorStore {
this.synchronizeSeriesPrecision(instance)
instance.override(indicator)
if (!isStack) {
this.removeInstance(paneId)
this.removeInstance({ paneId })
paneInstances = []
}
paneInstances.push(instance)
@ -84,32 +83,53 @@ export default class IndicatorStore {
return true
}
getInstances (paneId: string): IndicatorImp[] {
getInstanceByPaneId (paneId: string): IndicatorImp[] {
return this._instances.get(paneId) ?? []
}
removeInstance (paneId: string, name?: string): boolean {
getInstanceByFilter (filter: IndicatorFilter): Map<string, IndicatorImp[]> {
const find: ((indicators: IndicatorImp[], name?: string) => IndicatorImp[]) = (indicators, name) => {
return indicators.filter(indicator => {
return !isValid(name) || indicator.name === name
})
}
const { paneId, name } = filter
const map = new Map<string, IndicatorImp[]>()
if (isValid(paneId)) {
const indicators = this.getInstanceByPaneId(paneId)
map.set(paneId, find(indicators, name))
} else {
if (isValid(name)) {
const map = new Map<string, IndicatorImp[]>()
this._instances.forEach((indicators, paneId) => {
map.set(paneId, find(indicators, name))
})
} else {
this._instances.forEach((indicators, paneId) => {
map.set(paneId, find(indicators))
})
}
}
return map
}
removeInstance (filter: IndicatorFilter): boolean {
let removed = false
const paneInstances = this._instances.get(paneId)
if (isValid(paneInstances)) {
if (isString(name)) {
const index = paneInstances.findIndex(ins => ins.name === name)
const filterMap = this.getInstanceByFilter(filter)
filterMap.forEach((indicators, paneId) => {
const paneInstances = this.getInstanceByPaneId(paneId)
indicators.forEach(indicator => {
const index = paneInstances.findIndex(ins => ins.name === indicator.name)
if (index > -1) {
this._scheduler.removeTask(generateTaskId(paneId, name))
this._scheduler.removeTask(generateTaskId(paneId, indicator.name))
paneInstances.splice(index, 1)
removed = true
}
} else {
paneInstances.forEach(instance => {
this._scheduler.removeTask(generateTaskId(paneId, instance.name))
})
this._instances.set(paneId, [])
removed = true
}
if (this._instances.get(paneId)?.length === 0) {
})
if (paneInstances.length === 0) {
this._instances.delete(paneId)
}
}
})
return removed
}
@ -117,54 +137,13 @@ export default class IndicatorStore {
return this._instances.has(paneId)
}
calcInstance (name?: string, paneId?: string): void {
if (isString(name)) {
if (isString(paneId)) {
const paneInstances = this._instances.get(paneId)
if (isValid(paneInstances)) {
const instance = paneInstances.find(ins => ins.name === name)
if (isValid(instance)) {
this._addTask(paneId, instance)
}
}
} else {
this._instances.forEach((paneInstances, paneId) => {
const instance = paneInstances.find(ins => ins.name === name)
if (isValid(instance)) {
this._addTask(paneId, instance)
}
})
}
} else {
this._instances.forEach((paneInstances, paneId) => {
paneInstances.forEach(instance => {
this._addTask(paneId, instance)
})
calcInstance (filter: IndicatorFilter): void {
const filterMap = this.getInstanceByFilter(filter)
filterMap.forEach((indicators, paneId) => {
indicators.forEach(indicator => {
this._addTask(paneId, indicator)
})
}
}
getInstanceByPaneId (paneId?: string, name?: string): Nullable<Indicator> | Nullable<Map<string, Indicator>> | Map<string, Map<string, Indicator>> {
const createMapping: ((instances: IndicatorImp[]) => Map<string, Indicator>) = (instances: IndicatorImp[]) => {
const mapping = new Map<string, Indicator>()
instances.forEach(ins => {
mapping.set(ins.name, ins)
})
return mapping
}
if (isString(paneId)) {
const paneInstances = this._instances.get(paneId) ?? []
if (isString(name)) {
return paneInstances?.find(ins => ins.name === name) ?? null
}
return createMapping(paneInstances)
}
const mapping = new Map<string, Map<string, Indicator>>()
this._instances.forEach((instances, paneId) => {
mapping.set(paneId, createMapping(instances))
})
return mapping
}
synchronizeSeriesPrecision (indicator?: IndicatorImp): void {
@ -194,10 +173,10 @@ export default class IndicatorStore {
}
}
override (indicator: IndicatorCreate, paneId: Nullable<string>): boolean {
const { name } = indicator
override (indicator: IndicatorCreate): boolean {
const { name, paneId } = indicator
let instances = new Map<string, IndicatorImp[]>()
if (paneId !== null) {
if (isValid(paneId)) {
const paneInstances = this._instances.get(paneId)
if (isValid(paneInstances)) {
instances.set(paneId, paneInstances)

View File

@ -20,7 +20,7 @@ import { createId } from '../common/utils/id'
import { LoadDataType } from '../common/LoadDataCallback'
import type OverlayImp from '../component/Overlay'
import { type OverlayCreate, type OverlayRemove, OVERLAY_ID_PREFIX } from '../component/Overlay'
import { type OverlayCreate, OVERLAY_ID_PREFIX, type OverlayFilter } from '../component/Overlay'
import { getOverlayInnerClass } from '../extension/overlay/index'
@ -50,7 +50,7 @@ export interface EventOverlayInfo {
export default class OverlayStore {
private readonly _chartStore: ChartStore
private _instances = new Map<string, OverlayImp[]>()
private readonly _instances = new Map<string, OverlayImp[]>()
/**
* Overlay information in painting
@ -97,20 +97,48 @@ export default class OverlayStore {
this._chartStore = chartStore
}
getInstanceById (id: string): Nullable<OverlayImp> {
for (const entry of this._instances) {
const paneOverlays = entry[1]
const overlay = paneOverlays.find(o => o.id === id)
if (isValid(overlay)) {
return overlay
}
getInstanceByFilter (filter: OverlayFilter): Map<string, OverlayImp[]> {
const { id, groupId, paneId, name } = filter
const find: ((overlays: OverlayImp[]) => OverlayImp[]) = (overlays) => {
return overlays.filter(overlay => {
if (isValid(id)) {
return overlay.id === id
} else {
if (isValid(groupId)) {
return overlay.groupId === groupId && (!isValid(name) || overlay.name === name)
}
}
return !isValid(name) || overlay.name === name
})
}
if (this._progressInstanceInfo !== null) {
if (this._progressInstanceInfo.instance.id === id) {
return this._progressInstanceInfo.instance
}
const map = new Map<string, OverlayImp[]>()
if (isValid(paneId)) {
const overlays = this.getInstanceByPaneId(paneId)
map.set(paneId, find(overlays))
} else {
this._instances.forEach((overlays, paneId) => {
map.set(paneId, find(overlays))
})
}
return null
const progressOverlay = this._progressInstanceInfo?.instance
if (isValid(progressOverlay)) {
const paneOverlays = map.get(progressOverlay.paneId) ?? []
paneOverlays.push(progressOverlay)
map.set(progressOverlay.paneId, paneOverlays)
}
return map
}
getInstanceByPaneId (paneId?: string): OverlayImp[] {
if (!isString(paneId)) {
let overlays: OverlayImp[] = []
this._instances.forEach(paneOverlays => {
overlays = overlays.concat(paneOverlays)
})
return overlays
}
return this._instances.get(paneId) ?? []
}
private _sort (paneId?: string): void {
@ -123,39 +151,55 @@ export default class OverlayStore {
}
}
addInstances (overlays: OverlayCreate[], paneId: string, appointPaneFlag: boolean): Array<Nullable<string>> {
const ids = overlays.map(overlay => {
const id = overlay.id ?? createId(OVERLAY_ID_PREFIX)
if (this.getInstanceById(id) === null) {
const OverlayClazz = getOverlayInnerClass(overlay.name)
if (OverlayClazz !== null) {
const instance = new OverlayClazz()
instance.override({ paneId })
const groupId = overlay.groupId ?? id
overlay.id = id
overlay.paneId = paneId
overlay.groupId = groupId
instance.override(overlay)
if (instance.isDrawing()) {
this._progressInstanceInfo = { paneId, instance, appointPaneFlag }
} else {
if (!this._instances.has(paneId)) {
this._instances.set(paneId, [])
}
this._instances.get(paneId)?.push(instance)
addInstances (overlays: OverlayCreate[], appointPaneFlags: boolean[]): Array<Nullable<string>> {
const updatePaneIds: string[] = []
const ids = overlays.map((overlay, index) => {
if (isValid(overlay.id)) {
let findOverlay: Nullable<OverlayImp> = null
for (const [, overlays] of this._instances) {
const overlay = overlays.find(o => o.id === overlay.id)
if (isValid(overlay)) {
findOverlay = overlay
break
}
if (instance.isStart()) {
instance.onDrawStart?.(({ overlay: instance }))
}
return id
}
if (isValid(findOverlay)) {
return overlay.id
}
}
const OverlayClazz = getOverlayInnerClass(overlay.name)
if (isValid(OverlayClazz)) {
const id = overlay.id ?? createId(OVERLAY_ID_PREFIX)
const instance = new OverlayClazz()
const groupId = overlay.groupId ?? id
overlay.id = id
overlay.groupId = groupId
instance.override(overlay)
const paneId = instance.paneId
if (!updatePaneIds.includes(paneId)) {
updatePaneIds.push(paneId)
}
if (instance.isDrawing()) {
this._progressInstanceInfo = { paneId, instance, appointPaneFlag: appointPaneFlags[index] }
} else {
if (!this._instances.has(paneId)) {
this._instances.set(paneId, [])
}
this._instances.get(paneId)?.push(instance)
}
if (instance.isStart()) {
instance.onDrawStart?.(({ overlay: instance }))
}
return id
}
return null
})
if (ids.some(id => id !== null)) {
if (updatePaneIds.length > 0) {
this._sort()
const chart = this._chartStore.getChart()
chart.updatePane(UpdateLevel.Overlay, paneId)
updatePaneIds.forEach(paneId => {
chart.updatePane(UpdateLevel.Overlay, paneId)
})
chart.updatePane(UpdateLevel.Overlay, PaneIdConstants.X_AXIS)
}
return ids
@ -189,135 +233,61 @@ export default class OverlayStore {
}
}
getInstances (paneId?: string): OverlayImp[] {
if (!isString(paneId)) {
let instances: OverlayImp[] = []
this._instances.forEach(paneInstances => {
instances = instances.concat(paneInstances)
})
return instances
}
return this._instances.get(paneId) ?? []
}
override (overlay: Partial<OverlayCreate>): void {
const { id, groupId, name } = overlay
let updateFlag = false
let sortFlag = false
const setFlag: (instance: OverlayImp) => void = (instance: OverlayImp) => {
instance.override(overlay)
const { sort, draw } = instance.shouldUpdate()
if (draw) {
updateFlag = true
}
if (sort) {
sortFlag = true
}
}
if (isString(id)) {
const instance = this.getInstanceById(id)
if (instance !== null) {
setFlag(instance)
}
} else {
const nameValid = isString(name)
const groupIdValid = isString(groupId)
this._instances.forEach(paneInstances => {
paneInstances.forEach(instance => {
if (
(nameValid && instance.name === name) ||
(groupIdValid && instance.groupId === groupId) ||
(!nameValid && !groupIdValid)
) {
setFlag(instance)
}
})
})
if (this._progressInstanceInfo !== null) {
const progressInstance = this._progressInstanceInfo.instance
if (
(nameValid && progressInstance.name === name) ||
(groupIdValid && progressInstance.groupId === groupId) ||
(!nameValid && !groupIdValid)
) {
setFlag(progressInstance)
const updatePaneIds: string[] = []
const filterMap = this.getInstanceByFilter(overlay)
filterMap.forEach((instances, paneId) => {
instances.forEach(instance => {
instance.override(overlay)
const { sort, draw } = instance.shouldUpdate()
if (sort) {
sortFlag = true
}
}
}
if (sort || draw) {
if (!updatePaneIds.includes(paneId)) {
updatePaneIds.push(paneId)
}
}
})
})
if (sortFlag) {
this._sort()
}
if (updateFlag) {
this._chartStore.getChart().updatePane(UpdateLevel.Overlay)
if (updatePaneIds.length > 0) {
const chart = this._chartStore.getChart()
updatePaneIds.forEach(paneId => {
chart.updatePane(UpdateLevel.Overlay, paneId)
})
chart.updatePane(UpdateLevel.Overlay, PaneIdConstants.X_AXIS)
}
}
removeInstance (overlayRemove?: OverlayRemove): void {
const match: ((remove: OverlayRemove, overlay: OverlayImp) => boolean) = (remove: OverlayRemove, overlay: OverlayImp) => {
if (isString(remove.id)) {
if (overlay.id !== remove.id) {
return false
}
} else {
if (isString(remove.groupId)) {
if (overlay.groupId !== remove.groupId) {
return false
}
} else {
if (isString(remove.name)) {
if (overlay.name !== remove.name) {
return false
}
}
}
}
return true
}
removeInstance (filter: OverlayFilter): void {
const updatePaneIds: string[] = []
const overlayRemoveValid = isValid(overlayRemove)
if (this._progressInstanceInfo !== null) {
const { instance } = this._progressInstanceInfo
if (
!overlayRemoveValid ||
(overlayRemoveValid && match(overlayRemove, instance))
) {
updatePaneIds.push(this._progressInstanceInfo.paneId)
instance.onRemoved?.({ overlay: instance })
this._progressInstanceInfo = null
}
}
if (overlayRemoveValid) {
const instances = new Map<string, OverlayImp[]>()
for (const entry of this._instances) {
const paneInstances = entry[1]
const newPaneInstances = paneInstances.filter(instance => {
if (match(overlayRemove, instance)) {
if (!updatePaneIds.includes(entry[0])) {
updatePaneIds.push(entry[0])
}
instance.onRemoved?.({ overlay: instance })
return false
}
return true
})
if (newPaneInstances.length > 0) {
instances.set(entry[0], newPaneInstances)
const filterMap = this.getInstanceByFilter(filter)
filterMap.forEach((overlays, paneId) => {
const paneOverlays = this.getInstanceByPaneId(paneId)
overlays.forEach(overlay => {
overlay.onRemoved?.({ overlay })
if (!updatePaneIds.includes(paneId)) {
updatePaneIds.push(paneId)
}
if (overlay.isDrawing()) {
this._progressInstanceInfo = null
} else {
const index = paneOverlays.findIndex(o => o.id === overlay.id)
if (index > -1) {
paneOverlays.splice(index, 1)
}
}
if (paneOverlays.length === 0) {
this._instances.delete(paneId)
}
}
this._instances = instances
} else {
this._instances.forEach((paneInstances, paneId) => {
updatePaneIds.push(paneId)
paneInstances.forEach(instance => {
instance.onRemoved?.({ overlay: instance })
})
})
this._instances.clear()
}
})
if (updatePaneIds.length > 0) {
const chart = this._chartStore.getChart()
updatePaneIds.forEach(paneId => {

View File

@ -312,7 +312,6 @@ export default class TimeScaleStore {
// More processing and loading, more loading if there are callback methods and no data is being loaded
if (from === 0) {
const firstData = dataList[0]
this._chartStore.executeLoadMoreCallback(firstData?.timestamp ?? null)
this._chartStore.executeLoadDataCallback({
type: LoadDataType.Forward,
data: firstData ?? null

View File

@ -56,7 +56,7 @@ export default class CandleTooltipView extends IndicatorTooltipView {
const thousandsSeparator = chartStore.getThousandsSeparator()
const decimalFoldThreshold = chartStore.getDecimalFoldThreshold()
const activeIcon = chartStore.getTooltipStore().getActiveIcon()
const indicators = chartStore.getIndicatorStore().getInstances(pane.getId())
const indicators = chartStore.getIndicatorStore().getInstanceByPaneId(pane.getId())
const dateTimeFormat = chartStore.getTimeScaleStore().getDateTimeFormat()
const styles = chartStore.getStyles()
const candleStyles = styles.candle
@ -272,9 +272,9 @@ export default class CandleTooltipView extends IndicatorTooltipView {
if (isDrawIndicatorTooltip) {
ctx.font = createFont(indicatorTextSize, indicatorTextWeight, indicatorTextFamily)
indicators.forEach(indicator => {
const tooltipDataValues = this.getIndicatorTooltipData(dataList, crosshair, indicator, customApi, thousandsSeparator, decimalFoldThreshold, indicatorStyles).values ?? []
indicatorLegendsArray.push(tooltipDataValues)
tooltipDataValues.forEach(data => {
const tooltipDataLegends = this.getIndicatorTooltipData(dataList, crosshair, indicator, customApi, thousandsSeparator, decimalFoldThreshold, indicatorStyles).legends ?? []
indicatorLegendsArray.push(tooltipDataLegends)
tooltipDataLegends.forEach(data => {
const title = data.title as TooltipLegendChild
const value = data.value as TooltipLegendChild
const text = `${title.text}${value.text}`

View File

@ -70,7 +70,7 @@ export default class CrosshairHorizontalLabelView<C extends Axis = YAxis> extend
if (yAxis.isInCandle()) {
precision = chartStore.getPrecision().price
} else {
const indicators = chartStore.getIndicatorStore().getInstances(crosshair.paneId!)
const indicators = chartStore.getIndicatorStore().getInstanceByPaneId(crosshair.paneId!)
indicators.forEach(indicator => {
precision = Math.max(indicator.precision, precision)
if (!shouldFormatBigNumber) {

View File

@ -35,7 +35,7 @@ export default class IndicatorLastValueView extends View<YAxis> {
const yAxis = pane.getAxisComponent()
const dataList = chartStore.getDataList()
const dataIndex = dataList.length - 1
const indicators = chartStore.getIndicatorStore().getInstances(pane.getId())
const indicators = chartStore.getIndicatorStore().getInstanceByPaneId(pane.getId())
const thousandsSeparator = chartStore.getThousandsSeparator()
const decimalFoldThreshold = chartStore.getDecimalFoldThreshold()
indicators.forEach(indicator => {

View File

@ -58,7 +58,7 @@ export default class IndicatorTooltipView extends View<YAxis> {
const customApi = chartStore.getCustomApi()
const thousandsSeparator = chartStore.getThousandsSeparator()
const decimalFoldThreshold = chartStore.getDecimalFoldThreshold()
const indicators = chartStore.getIndicatorStore().getInstances(pane.getId())
const indicators = chartStore.getIndicatorStore().getInstanceByPaneId(pane.getId())
const activeIcon = chartStore.getTooltipStore().getActiveIcon()
const defaultStyles = chartStore.getStyles().indicator
const { offsetLeft, offsetTop, offsetRight } = defaultStyles.tooltip
@ -93,7 +93,7 @@ export default class IndicatorTooltipView extends View<YAxis> {
indicators.forEach(indicator => {
let prevRowHeight = 0
const coordinate = { x: left, y: top }
const { name, calcParamsText, values: legends, icons } = this.getIndicatorTooltipData(dataList, crosshair, indicator, customApi, thousandsSeparator, decimalFoldThreshold, styles)
const { name, calcParamsText, legends, icons } = this.getIndicatorTooltipData(dataList, crosshair, indicator, customApi, thousandsSeparator, decimalFoldThreshold, styles)
const nameValid = name.length > 0
const legendValid = legends.length > 0
if (nameValid || legendValid) {
@ -276,7 +276,7 @@ export default class IndicatorTooltipView extends View<YAxis> {
calcParamsText = `(${calcParams.join(',')})`
}
const tooltipData: IndicatorTooltipData = { name, calcParamsText, values: [], icons: tooltipStyles.icons }
const tooltipData: IndicatorTooltipData = { name, calcParamsText, legends: [], icons: tooltipStyles.icons }
const dataIndex = crosshair.dataIndex!
const result = indicator.result ?? []
@ -297,14 +297,14 @@ export default class IndicatorTooltipView extends View<YAxis> {
legends.push({ title: { text: figure.title, color }, value: { text: formatFoldDecimal(formatThousands((value ?? tooltipStyles.defaultValue) as string, thousandsSeparator), decimalFoldThreshold), color } })
}
})
tooltipData.values = legends
tooltipData.legends = legends
}
if (indicator.createTooltipDataSource !== null) {
const widget = this.getWidget()
const pane = widget.getPane()
const chartStore = pane.getChart().getChartStore()
const { name: customName, calcParamsText: customCalcParamsText, values: customLegends, icons: customIcons } = indicator.createTooltipDataSource({
const { name: customName, calcParamsText: customCalcParamsText, legends: customLegends, icons: customIcons } = indicator.createTooltipDataSource({
kLineDataList: dataList,
indicator,
visibleRange: chartStore.getTimeScaleStore().getVisibleRange(),
@ -342,7 +342,7 @@ export default class IndicatorTooltipView extends View<YAxis> {
value.text = formatFoldDecimal(formatThousands(value.text, thousandsSeparator), decimalFoldThreshold)
optimizedLegends.push({ title, value })
})
tooltipData.values = optimizedLegends
tooltipData.legends = optimizedLegends
}
}
return tooltipData

View File

@ -31,7 +31,7 @@ export default class IndicatorView extends CandleBarView {
const pane = this.getWidget().getPane()
const yAxis = pane.getAxisComponent()
if (!yAxis.isInCandle()) {
const indicators = chartStore.getIndicatorStore().getInstances(pane.getId())
const indicators = chartStore.getIndicatorStore().getInstanceByPaneId(pane.getId())
for (const indicator of indicators) {
if (indicator.shouldOhlc && indicator.visible) {
const indicatorStyles = indicator.styles
@ -71,7 +71,7 @@ export default class IndicatorView extends CandleBarView {
const dataList = chartStore.getDataList()
const timeScaleStore = chartStore.getTimeScaleStore()
const visibleRange = timeScaleStore.getVisibleRange()
const indicators = chartStore.getIndicatorStore().getInstances(pane.getId())
const indicators = chartStore.getIndicatorStore().getInstanceByPaneId(pane.getId())
const defaultStyles = chartStore.getStyles().indicator
ctx.save()
indicators.forEach(indicator => {

View File

@ -392,7 +392,7 @@ export default class OverlayView<C extends Axis = YAxis> extends View<C> {
const hoverInstanceInfo = overlayStore.getHoverInstanceInfo()
const clickInstanceInfo = overlayStore.getClickInstanceInfo()
const overlays = this.getCompleteOverlays(overlayStore, paneId)
const paneIndicators = chartStore.getIndicatorStore().getInstances(paneId)
const paneIndicators = chartStore.getIndicatorStore().getInstanceByPaneId(paneId)
const overlayPrecision = paneIndicators.reduce((prev, indicator) => {
const precision = indicator.precision
prev[indicator.name] = precision
@ -512,7 +512,7 @@ export default class OverlayView<C extends Axis = YAxis> extends View<C> {
}
protected getCompleteOverlays (overlayStore: OverlayStore, paneId: string): OverlayImp[] {
return overlayStore.getInstances(paneId)
return overlayStore.getInstanceByPaneId(paneId)
}
protected getProgressOverlay (info: ProgressOverlayInfo, paneId: string): Nullable<OverlayImp> {

View File

@ -42,7 +42,7 @@ export default class OverlayXAxisView extends OverlayYAxisView<XAxis> {
}
override getCompleteOverlays (overlayStore: OverlayStore): OverlayImp[] {
return overlayStore.getInstances()
return overlayStore.getInstanceByPaneId()
}
override getProgressOverlay (info: ProgressOverlayInfo): OverlayImp {