Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two price scales #290

Merged
merged 55 commits into from
May 15, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
5a373de
129: two price scales
eugene-korobko Dec 19, 2019
59f0122
129: Fixed overlay behavior
eugene-korobko Dec 24, 2019
a5658f4
129: Fixed graph tests
eugene-korobko Dec 24, 2019
4420961
129: Fixed tslint
eugene-korobko Dec 24, 2019
b9fe1ca
129: Fixed review issues
eugene-korobko Dec 30, 2019
f527624
129: Fixed applying options, added tests
eugene-korobko Dec 30, 2019
73d74c4
129: Improved test
eugene-korobko Dec 31, 2019
d217577
129: Step to new API
eugene-korobko Jan 30, 2020
a6f469b
129: New scales API
eugene-korobko Feb 3, 2020
6b7b792
129: Added doc
eugene-korobko Feb 3, 2020
1be67d2
129: Added graphic tests
eugene-korobko Feb 4, 2020
2ac0db7
129: Fixed processing empty price scale id
eugene-korobko Feb 4, 2020
ae6e1ef
Update src/api/chart-api.ts
eugene-korobko Feb 4, 2020
bd8a3b7
Update src/api/chart-api.ts
eugene-korobko Feb 4, 2020
4e89f7c
Update src/api/chart-api.ts
eugene-korobko Feb 4, 2020
6523a38
Update src/api/chart-api.ts
eugene-korobko Feb 4, 2020
cc734e5
129: Updated docs
eugene-korobko Feb 4, 2020
7fae31f
129: Fixed review issues
eugene-korobko Feb 4, 2020
d77d862
Merge branch 'master' into 129-two-price-axises
eugene-korobko Feb 4, 2020
5409713
129: Fixed applying price scale options
eugene-korobko Feb 6, 2020
c824a58
129: Fixed review issues & tests
eugene-korobko Feb 26, 2020
55aab16
129: Improved typings, added docs
eugene-korobko Feb 28, 2020
0ac12ae
129: Fixed review issues
eugene-korobko Mar 10, 2020
9352908
129: Fixed review issues
eugene-korobko Mar 11, 2020
897c89a
Merge branch 'master' into 129-two-price-axises
eugene-korobko Mar 11, 2020
e38f1ed
129: Fixed backward compatibility
eugene-korobko Mar 12, 2020
97807f5
Updated docs
timocov Mar 19, 2020
599f403
Review style fixes
timocov Mar 19, 2020
21d8974
Fixed build
timocov Mar 19, 2020
1091990
129: Fixed review issues
eugene-korobko Mar 20, 2020
5b1618c
129: Fixed review issues
eugene-korobko Mar 26, 2020
bd75723
129: Fixed linter
eugene-korobko Mar 26, 2020
c152897
129: Fixed linter
eugene-korobko Mar 26, 2020
79402ae
129: Throw exception instead of log
eugene-korobko Mar 27, 2020
8607967
A bit refactored debug messages/errors
timocov Mar 27, 2020
5ba818f
129: Removed PriceScaleAPI cache, improved docs
eugene-korobko Mar 27, 2020
cfc39d7
Apply suggestions from code review
timocov Mar 30, 2020
e3b1453
Update codechecks to pass test
timocov Mar 30, 2020
6245190
Fixed types
timocov Mar 30, 2020
a862876
Merge branch 'master' into 129-two-price-axises
timocov Mar 30, 2020
7630844
Fixed codechecks config after merge master
timocov Mar 30, 2020
26ce7ab
129: Fixed applying scale margins to series
eugene-korobko Mar 30, 2020
c2186f6
Merge branch 'master' into 129-two-price-axises
eugene-korobko Apr 16, 2020
0c748c4
129: Implemented moving series from scale to scale
eugene-korobko Apr 17, 2020
8ce22fb
129: Fixed typo in docs
eugene-korobko Apr 17, 2020
8d69e87
129: Fixed review issues
eugene-korobko Apr 17, 2020
40eebef
129: Fixed review issues
eugene-korobko Apr 22, 2020
9387fa8
Don't generate random price scale id if empty id passed
timocov Apr 29, 2020
19d4823
Fixed tslint error
timocov Apr 29, 2020
2835775
Removed useless method containsSeries
timocov Apr 30, 2020
7e1e0a3
Removed unused hasSeries method
timocov Apr 30, 2020
7e8e764
Extracted default price scales to separate module to avoid circular d…
timocov Apr 30, 2020
9673493
Removed unused method setPriceAutoScaleForAllMainSources
timocov Apr 30, 2020
043145f
Merge branch 'master' into 129-two-price-axises
eugene-korobko May 7, 2020
06ebec2
Merge branch 'master' into 129-two-price-axises
eugene-korobko May 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 38 additions & 23 deletions src/gui/chart-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ChartModel, ChartOptions } from '../model/chart-model';
import { Coordinate } from '../model/coordinate';
import { InvalidateMask, InvalidationLevel } from '../model/invalidate-mask';
import { Point } from '../model/point';
import { PriceAxisPosition } from '../model/price-scale';
import { Series } from '../model/series';
import { TimePoint, TimePointIndex } from '../model/time-data';

Expand All @@ -33,10 +34,11 @@ export class ChartWidget implements IDestroyable {
private _paneSeparators: PaneSeparator[] = [];
private readonly _model: ChartModel;
private _drawRafId: number = 0;
private readonly _priceAxisWidthChanged: Delegate<number> = new Delegate();
private readonly _priceAxisWidthChanged: Delegate<number, PriceAxisPosition> = new Delegate();
timocov marked this conversation as resolved.
Show resolved Hide resolved
private _height: number = 0;
private _width: number = 0;
private _priceAxisWidth: number = 0;
private _leftPriceAxisWidth: number = 0;
private _rightPriceAxisWidth: number = 0;
private _element: HTMLElement;
private readonly _tableElement: HTMLElement;
private _timeAxisWidget: TimeAxisWidget;
Expand Down Expand Up @@ -217,11 +219,11 @@ export class ChartWidget implements IDestroyable {
let targetX = 0;
let targetY = 0;

const drawPriceAxises = () => {
const drawPriceAxises = (position: PriceAxisPosition) => {
for (let paneIndex = 0; paneIndex < this._paneWidgets.length; paneIndex++) {
const paneWidget = this._paneWidgets[paneIndex];
const paneWidgetHeight = paneWidget.getSize().h;
const priceAxisWidget = ensureNotNull(paneWidget.priceAxisWidget());
const priceAxisWidget = ensureNotNull(position === 'left' ? paneWidget.leftPriceAxisWidget() : paneWidget.rightPriceAxisWidget());
const image = priceAxisWidget.getImage();
ctx.drawImage(image, targetX, targetY, priceAxisWidget.getWidth(), paneWidgetHeight);
targetY += paneWidgetHeight;
Expand All @@ -231,9 +233,9 @@ export class ChartWidget implements IDestroyable {
}
};
// draw left price scale if exists
if (this._options.priceScale.position === 'left') {
drawPriceAxises();
targetX = ensureNotNull(firstPane.priceAxisWidget()).getWidth();
if (this._options.priceScale.position === 'left' || this._options.priceScale.position === 'both') {
drawPriceAxises('left');
targetX = ensureNotNull(firstPane.leftPriceAxisWidget()).getWidth();
}
targetY = 0;
for (let paneIndex = 0; paneIndex < this._paneWidgets.length; paneIndex++) {
Expand All @@ -253,10 +255,10 @@ export class ChartWidget implements IDestroyable {
targetX += firstPane.getSize().w;
if (this._options.priceScale.position === 'right') {
timocov marked this conversation as resolved.
Show resolved Hide resolved
targetY = 0;
drawPriceAxises();
drawPriceAxises('right');
}
const drawStub = () => {
const stub = ensureNotNull(this._timeAxisWidget.stub());
const drawStub = (position: PriceAxisPosition) => {
const stub = ensureNotNull(position === 'left' ? this._timeAxisWidget.leftStub() : this._timeAxisWidget.rightStub());
const size = stub.getSize();
const image = stub.getImage();
ctx.drawImage(image, targetX, targetY, size.w, size.h);
Expand All @@ -265,29 +267,34 @@ export class ChartWidget implements IDestroyable {
if (this._options.timeScale.visible) {
targetX = 0;
if (this._options.priceScale.position === 'left') {
timocov marked this conversation as resolved.
Show resolved Hide resolved
drawStub();
targetX = ensureNotNull(firstPane.priceAxisWidget()).getWidth();
drawStub('left');
targetX = ensureNotNull(firstPane.leftPriceAxisWidget()).getWidth();
}
const size = this._timeAxisWidget.getSize();
const image = this._timeAxisWidget.getImage();
ctx.drawImage(image, targetX, targetY, size.w, size.h);
if (this._options.priceScale.position === 'right') {
timocov marked this conversation as resolved.
Show resolved Hide resolved
targetX = firstPane.getSize().w;
drawStub();
drawStub('right');
ctx.restore();
}
}

return targetCanvas;
}

// tslint:disable-next-line:cyclomatic-complexity
private _adjustSizeImpl(): void {
let totalStretch = 0;
let priceAxisWidth = 0;
let leftPriceAxisWidth = 0;
let rightPriceAxisWidth = 0;

for (const paneWidget of this._paneWidgets) {
if (this._options.priceScale.position !== 'none') {
priceAxisWidth = Math.max(priceAxisWidth, ensureNotNull(paneWidget.priceAxisWidget()).optimalWidth());
if (this._options.priceScale.position === 'left' || this._options.priceScale.position === 'both') {
timocov marked this conversation as resolved.
Show resolved Hide resolved
leftPriceAxisWidth = Math.max(leftPriceAxisWidth, ensureNotNull(paneWidget.leftPriceAxisWidget()).optimalWidth());
}
if (this._options.priceScale.position === 'right' || this._options.priceScale.position === 'both') {
rightPriceAxisWidth = Math.max(rightPriceAxisWidth, ensureNotNull(paneWidget.rightPriceAxisWidget()).optimalWidth());
}

totalStretch += paneWidget.stretchFactor();
Expand All @@ -296,7 +303,7 @@ export class ChartWidget implements IDestroyable {
const width = this._width;
const height = this._height;

const paneWidth = Math.max(width - priceAxisWidth, 0);
const paneWidth = Math.max(width - leftPriceAxisWidth - rightPriceAxisWidth, 0);

const separatorCount = this._paneSeparators.length;
const separatorHeight = SEPARATOR_HEIGHT;
Expand Down Expand Up @@ -325,8 +332,11 @@ export class ChartWidget implements IDestroyable {
accumulatedHeight += paneHeight;

paneWidget.setSize(new Size(paneWidth, paneHeight));
if (this._options.priceScale.position !== 'none') {
paneWidget.setPriceAxisSize(priceAxisWidth);
if (this._options.priceScale.position === 'left' || this._options.priceScale.position === 'both') {
paneWidget.setPriceAxisSize(leftPriceAxisWidth, 'left');
}
if (this._options.priceScale.position === 'right' || this._options.priceScale.position === 'both') {
paneWidget.setPriceAxisSize(rightPriceAxisWidth, 'right');
}

if (paneWidget.state()) {
Expand All @@ -336,13 +346,18 @@ export class ChartWidget implements IDestroyable {

this._timeAxisWidget.setSizes(
new Size(paneWidth, timeAxisHeight),
priceAxisWidth
leftPriceAxisWidth,
rightPriceAxisWidth
);

this._model.setWidth(paneWidth);
if (this._priceAxisWidth !== priceAxisWidth) {
this._priceAxisWidth = priceAxisWidth;
this._priceAxisWidthChanged.fire(priceAxisWidth);
if (this._leftPriceAxisWidth !== leftPriceAxisWidth) {
this._leftPriceAxisWidth = leftPriceAxisWidth;
this._priceAxisWidthChanged.fire(leftPriceAxisWidth, 'left');
}
if (this._rightPriceAxisWidth !== rightPriceAxisWidth) {
this._rightPriceAxisWidth = rightPriceAxisWidth;
this._priceAxisWidthChanged.fire(rightPriceAxisWidth, 'right');
}
}

Expand Down
73 changes: 46 additions & 27 deletions src/gui/pane-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { IPaneView } from '../views/pane/ipane-view';
import { clearRect, createBoundCanvas, getPretransformedContext2D, Size } from './canvas-utils';
import { ChartWidget } from './chart-widget';
import { MouseEventHandler, Position, TouchMouseEvent } from './mouse-event-handler';
import { PriceAxisWidget } from './price-axis-widget';
import { PriceAxisWidget, PriceAxisWidgetSide } from './price-axis-widget';
import { isMobile, mobileTouch } from './support-touch';

// actually we should check what event happened (touch or mouse)
Expand All @@ -40,7 +40,8 @@ export class PaneWidget implements IDestroyable {
private readonly _chart: ChartWidget;
private _state: Pane | null;
private _size: Size = new Size(0, 0);
private _priceAxisWidget: PriceAxisWidget | null = null;
private _leftPriceAxisWidget: PriceAxisWidget | null = null;
private _rightPriceAxisWidget: PriceAxisWidget | null = null;
private readonly _paneCell: HTMLElement;
private readonly _leftAxisCell: HTMLElement;
private readonly _rightAxisCell: HTMLElement;
Expand Down Expand Up @@ -118,8 +119,11 @@ export class PaneWidget implements IDestroyable {
}

public destroy(): void {
if (this._priceAxisWidget !== null) {
this._priceAxisWidget.destroy();
if (this._leftPriceAxisWidget !== null) {
this._leftPriceAxisWidget.destroy();
}
if (this._rightPriceAxisWidget !== null) {
this._rightPriceAxisWidget.destroy();
}

this._topCanvasBinding.unsubscribeCanvasConfigured(this._topCanvasConfiguredHandler);
Expand Down Expand Up @@ -166,16 +170,22 @@ export class PaneWidget implements IDestroyable {
}

public updatePriceAxisWidget(): void {
if (this._state === null || this._priceAxisWidget === null) {
if (this._state === null) {
return;
}

if (this._model().serieses().length === 0) {
return;
}

const priceScale = this._state.defaultPriceScale();
this._priceAxisWidget.setPriceScale(ensureNotNull(priceScale));
if (this._leftPriceAxisWidget !== null) {
const leftPriceScale = this._state.leftPriceScale();
this._leftPriceAxisWidget.setPriceScale(ensureNotNull(leftPriceScale));
}
if (this._rightPriceAxisWidget !== null) {
const rightPriceScale = this._state.rightPriceScale();
this._rightPriceAxisWidget.setPriceScale(ensureNotNull(rightPriceScale));
}
}

public stretchFactor(): number {
Expand Down Expand Up @@ -426,8 +436,9 @@ export class PaneWidget implements IDestroyable {
return null;
}

public setPriceAxisSize(width: number): void {
ensureNotNull(this._priceAxisWidget).setSize(new Size(width, this._size.h));
public setPriceAxisSize(width: number, position: PriceAxisWidgetSide): void {
const priceAxisWidget = position === 'left' ? this._leftPriceAxisWidget : this._rightPriceAxisWidget;
ensureNotNull(priceAxisWidget).setSize(new Size(width, this._size.h));
}

public getSize(): Size {
Expand Down Expand Up @@ -487,8 +498,11 @@ export class PaneWidget implements IDestroyable {
this.recalculatePriceScale();
}

if (this._priceAxisWidget !== null) {
this._priceAxisWidget.paint(type);
if (this._leftPriceAxisWidget !== null) {
this._leftPriceAxisWidget.paint(type);
}
if (this._rightPriceAxisWidget !== null) {
this._rightPriceAxisWidget.paint(type);
}

if (type !== InvalidationLevel.Cursor) {
Expand All @@ -506,8 +520,12 @@ export class PaneWidget implements IDestroyable {
this._drawCrosshair(topCtx);
}

public priceAxisWidget(): PriceAxisWidget | null {
return this._priceAxisWidget;
public leftPriceAxisWidget(): PriceAxisWidget | null {
return this._leftPriceAxisWidget;
}

public rightPriceAxisWidget(): PriceAxisWidget | null {
return this._rightPriceAxisWidget;
}

private _backgroundColor(): string {
Expand Down Expand Up @@ -662,27 +680,28 @@ export class PaneWidget implements IDestroyable {
if (this._priceAxisPosition === axisPosition) {
return;
}
if (this._priceAxisWidget !== null) {
if (this._priceAxisWidget.isLeft()) {
this._leftAxisCell.removeChild(this._priceAxisWidget.getElement());
} else {
this._rightAxisCell.removeChild(this._priceAxisWidget.getElement());
}

this._priceAxisWidget.destroy();
this._priceAxisWidget = null;
if (this._leftPriceAxisWidget !== null) {
this._leftAxisCell.removeChild(this._leftPriceAxisWidget.getElement());
this._leftPriceAxisWidget.destroy();
this._leftPriceAxisWidget = null;
}
if (this._rightPriceAxisWidget !== null) {
this._rightAxisCell.removeChild(this._rightPriceAxisWidget.getElement());
this._rightPriceAxisWidget.destroy();
this._rightPriceAxisWidget = null;
}

if (axisPosition !== 'none') {
const rendererOptionsProvider = chart.model().rendererOptionsProvider();
this._priceAxisWidget = new PriceAxisWidget(this, chart.options().layout, rendererOptionsProvider, axisPosition);

if (axisPosition === 'left') {
this._leftAxisCell.appendChild(this._priceAxisWidget.getElement());
if (axisPosition === 'left' || axisPosition === 'both') {
this._leftPriceAxisWidget = new PriceAxisWidget(this, chart.options().layout, rendererOptionsProvider, 'left');
this._leftAxisCell.appendChild(this._leftPriceAxisWidget.getElement());
}

if (axisPosition === 'right') {
this._rightAxisCell.appendChild(this._priceAxisWidget.getElement());
if (axisPosition === 'right' || axisPosition === 'both') {
this._rightPriceAxisWidget = new PriceAxisWidget(this, chart.options().layout, rendererOptionsProvider, 'right');
this._rightAxisCell.appendChild(this._rightPriceAxisWidget.getElement());
}
}
this._priceAxisPosition = axisPosition;
Expand Down
Loading