Загрузка данных


protected createAxisSegments(from: number | null, to: number | null): AxisSegment[] {
  if ((!this.isSelected() && !this.isCreationPending()) || from === null || to === null) {
    return [];
  }

  return [
    {
      from,
      to,
      color: getThemeStore().colors.axisMarkerAreaFill,
    },
  ];
}

protected handleTwoPointCreation(
  event: PointerEvent,
  point: Point,
  startDrawing: (point: Point) => void,
  updateDrawing: (point: Point) => void,
  finishDrawing: () => void,
): boolean {
  if (this.mode !== 'idle' && this.mode !== 'drawing') {
    return false;
  }

  event.preventDefault();
  event.stopPropagation();

  if (this.mode === 'idle') {
    startDrawing(point);
  } else {
    updateDrawing(point);
    finishDrawing();
  }

  return true;
}





protected getTimeAxisSegments(): AxisSegment[] {
  const bounds = this.getTimeBounds();

  return this.createAxisSegments(bounds?.left ?? null, bounds?.right ?? null);
}

protected getPriceAxisSegments(): AxisSegment[] {
  const bounds = this.getPriceBounds();

  return this.createAxisSegments(bounds?.top ?? null, bounds?.bottom ?? null);
}

protected handlePointerDown = (event: PointerEvent): void => {
  if (this.hidden || event.button !== 0) {
    return;
  }

  const point = this.getEventPoint(event);

  if (
    this.handleTwoPointCreation(
      event,
      point,
      (nextPoint) => this.startDrawing(nextPoint),
      (nextPoint) => this.updateDrawing(nextPoint),
      () => this.finishDrawing(),
    )
  ) {
    return;
  }

  if (this.mode !== 'ready') {
    return;
  }

  if (!this.isSelected()) {
    if (!this.containsPoint(point)) {
      return;
    }

    event.preventDefault();
    event.stopPropagation();

    this.select();
    return;
  }

  const dragTarget = this.getDragTarget(point);

  if (!dragTarget) {
    this.deselect();
    return;
  }

  event.preventDefault();
  event.stopPropagation();

  this.startDragging(point, event.pointerId, dragTarget);
};




protected getTimeAxisSegments(): AxisSegment[] {
  const bounds = this.getTimeBounds();

  return this.createAxisSegments(bounds?.left ?? null, bounds?.right ?? null);
}

protected getPriceAxisSegments(): AxisSegment[] {
  const bounds = this.getPriceBounds();

  return this.createAxisSegments(bounds?.top ?? null, bounds?.bottom ?? null);
}

protected handlePointerDown = (event: PointerEvent): void => {
  if (this.hidden || event.button !== 0) {
    return;
  }

  const point = this.getEventPoint(event);

  if (
    this.handleTwoPointCreation(
      event,
      point,
      (nextPoint) => this.startDrawing(nextPoint),
      (nextPoint) => this.updateDrawing(nextPoint),
      () => this.finishDrawing(),
    )
  ) {
    return;
  }

  if (this.mode !== 'ready') {
    return;
  }

  if (!this.isSelected()) {
    if (!this.containsPoint(point)) {
      return;
    }

    event.preventDefault();
    event.stopPropagation();

    this.select();
    return;
  }

  const dragTarget = this.getDragTarget(point);

  if (!dragTarget) {
    this.deselect();
    return;
  }

  event.preventDefault();
  event.stopPropagation();

  this.startDragging(point, event.pointerId, dragTarget);
};




protected getTimeAxisSegments(): AxisSegment[] {
  const bounds = this.getTimeBounds();

  return this.createAxisSegments(bounds?.left ?? null, bounds?.right ?? null);
}

protected getPriceAxisSegments(): AxisSegment[] {
  const bounds = this.getPriceBounds();

  return this.createAxisSegments(bounds?.top ?? null, bounds?.bottom ?? null);
}


protected handlePointerDown = (event: PointerEvent): void => {
  if (this.hidden || event.button !== 0) {
    return;
  }

  const point = this.getEventPoint(event);

  if (
    this.handleTwoPointCreation(
      event,
      point,
      (nextPoint) => this.startDrawing(nextPoint),
      (nextPoint) => this.updateDrawing(nextPoint),
      () => this.finishDrawing(),
    )
  ) {
    return;
  }

  if (this.mode !== 'ready') {
    return;
  }

  if (!this.isSelected()) {
    if (!this.containsPoint(point)) {
      return;
    }

    event.preventDefault();
    event.stopPropagation();

    this.select();
    return;
  }

  const dragTarget = this.getDragTarget(point);

  if (!dragTarget) {
    this.deselect();
    return;
  }

  event.preventDefault();
  event.stopPropagation();

  this.startDragging(point, event.pointerId, dragTarget);
};





protected getTimeAxisSegments(): AxisSegment[] {
  const geometry = this.getGeometry();

  return this.createAxisSegments(geometry?.left ?? null, geometry?.right ?? null);
}

protected getPriceAxisSegments(): AxisSegment[] {
  const geometry = this.getGeometry();

  return this.createAxisSegments(geometry?.top ?? null, geometry?.bottom ?? null);
}

if (
  this.handleTwoPointCreation(
    event,
    point,
    (nextPoint) => this.startDrawing(nextPoint),
    (nextPoint) => this.updateDrawing(nextPoint),
    () => this.finishDrawing(),
  )
) {
  return;
}

if (this.mode !== 'ready') {




protected getTimeAxisSegments(): AxisSegment[] {
  const geometry = this.getGeometry();

  if (!geometry) {
    return [];
  }

  return this.createAxisSegments(
    Math.min(geometry.startPoint.x, geometry.directionPoint.x),
    Math.max(geometry.startPoint.x, geometry.directionPoint.x),
  );
}

protected getPriceAxisSegments(): AxisSegment[] {
  const geometry = this.getGeometry();

  if (!geometry) {
    return [];
  }

  return this.createAxisSegments(
    Math.min(geometry.startPoint.y, geometry.directionPoint.y),
    Math.max(geometry.startPoint.y, geometry.directionPoint.y),
  );
}


if (
  this.handleTwoPointCreation(
    event,
    point,
    (nextPoint) => this.startDrawing(nextPoint),
    (nextPoint) => this.updateDrawing(nextPoint),
    () => this.finishDrawing(),
  )
) {
  return;
}

if (this.mode !== 'ready') {
  return;
}





protected getTimeAxisSegments(): AxisSegment[] {
  const geometry = this.getGeometry();

  return this.createAxisSegments(geometry?.left ?? null, geometry?.right ?? null);
}

protected getPriceAxisSegments(): AxisSegment[] {
  const geometry = this.getGeometry();

  if (!geometry) {
    return [];
  }

  return this.createAxisSegments(
    Math.min(geometry.baseStartPoint.y, geometry.baseEndPoint.y),
    Math.max(geometry.baseStartPoint.y, geometry.baseEndPoint.y),
  );
}



protected getTimeAxisLabel(kind: string): AxisLabel | null {
  if ((!this.isSelected() && !this.isCreationPending()) || (kind !== 'start' && kind !== 'end')) {
    return null;
  }

  const time = kind === 'start' ? this.startTime : this.endTime;

  if (typeof time !== 'number') {
    return null;
  }

  const coordinate = getXCoordinateFromTime(this.chart, time, this.series);

  return createAxisLabel(
    coordinate,
    formatDate(
      time as UTCTimestamp,
      this.displayFormat.dateFormat,
      this.displayFormat.timeFormat,
      this.displayFormat.showTime,
    ),
  );
}


protected getPriceAxisLabel(kind: string): AxisLabel | null {
  if ((!this.isSelected() && !this.isCreationPending()) || (kind !== 'start' && kind !== 'end')) {
    return null;
  }

  const geometry = this.getGeometry();

  if (!geometry) {
    return null;
  }

  const price = kind === 'start' ? geometry.baseStartPrice : geometry.baseEndPrice;

  return createAxisLabel(getYCoordinateFromPrice(this.series, price), formatPrice(price));
}





export function getDistanceToSegment(point: Point, startPoint: Point, endPoint: Point): number {
  const deltaX = endPoint.x - startPoint.x;
  const deltaY = endPoint.y - startPoint.y;

  if (deltaX === 0 && deltaY === 0) {
    return Math.hypot(point.x - startPoint.x, point.y - startPoint.y);
  }

  const ratio = Math.max(
    0,
    Math.min(
      1,
      ((point.x - startPoint.x) * deltaX + (point.y - startPoint.y) * deltaY) /
        (deltaX * deltaX + deltaY * deltaY),
    ),
  );

  const projectionX = startPoint.x + ratio * deltaX;
  const projectionY = startPoint.y + ratio * deltaY;

  return Math.hypot(point.x - projectionX, point.y - projectionY);
}