-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Osama/DERG-1442/Add closed accumulator barriers (#291)
- add Accumulators closed barrier indicator
- Loading branch information
1 parent
25d1398
commit 0a3353f
Showing
7 changed files
with
384 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
...sualization/annotations/barriers/accumulators_barriers/accumulators_closed_indicator.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import 'package:deriv_chart/deriv_chart.dart'; | ||
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/chart_series/series_painter.dart'; | ||
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/models/accumulator_object.dart'; | ||
|
||
import 'accumulators_closed_indicator_painter.dart'; | ||
|
||
/// Accumulator Closed Contract Barriers. | ||
class AccumulatorsClosedIndicator extends ChartAnnotation<AccumulatorObject> { | ||
/// Initializes a tick indicator. | ||
AccumulatorsClosedIndicator( | ||
this.exitTick, { | ||
required this.lowBarrier, | ||
required this.highBarrier, | ||
required this.highBarrierDisplay, | ||
required this.lowBarrierDisplay, | ||
required this.barrierSpotDistance, | ||
required this.barrierEpoch, | ||
required this.activeContract, | ||
this.barrierEndEpoch, | ||
super.style, | ||
String? id, | ||
}) : super(id ?? 'AccumulatorsClosedIndicator'); | ||
|
||
/// The price difference between the barrier and the barrier Tick quote. | ||
final String barrierSpotDistance; | ||
|
||
/// The which this tick indicator will be pointing to. | ||
final Tick exitTick; | ||
|
||
/// The low barrier value. | ||
final double lowBarrier; | ||
|
||
/// The high barrier value. | ||
final double highBarrier; | ||
|
||
/// The low barrier display value. | ||
final String highBarrierDisplay; | ||
|
||
/// The high barrier display value. | ||
final String lowBarrierDisplay; | ||
|
||
/// [Optional] Active contract information. | ||
final AccumulatorsActiveContract? activeContract; | ||
|
||
/// The [epoch] of the tick that the barriers belong to. | ||
final int barrierEpoch; | ||
|
||
/// The End if the barrier, if [null] the barriers will go to the end of the screen. | ||
final int? barrierEndEpoch; | ||
|
||
@override | ||
SeriesPainter<Series> createPainter() => | ||
AccumulatorsClosedIndicatorPainter(this); | ||
|
||
@override | ||
AccumulatorObject createObject() => AccumulatorObject( | ||
tick: exitTick, | ||
barrierEpoch: barrierEpoch, | ||
lowBarrier: lowBarrier, | ||
highBarrier: highBarrier, | ||
profit: activeContract?.profit, | ||
barrierEndEpoch: barrierEndEpoch, | ||
); | ||
|
||
@override | ||
int? getMaxEpoch() => barrierEpoch; | ||
|
||
@override | ||
int? getMinEpoch() => barrierEpoch; | ||
|
||
@override | ||
List<double> recalculateMinMax() { | ||
if (annotationObject.bottomValue == null || | ||
annotationObject.topValue == null || | ||
!isOnRange) { | ||
return <double>[double.nan, double.nan]; | ||
} | ||
final double halfOfBarriersDelta = | ||
(annotationObject.highBarrier - annotationObject.lowBarrier) / 2; | ||
|
||
return <double>[ | ||
annotationObject.bottomValue! - halfOfBarriersDelta, | ||
annotationObject.topValue! + halfOfBarriersDelta, | ||
]; | ||
} | ||
} |
256 changes: 256 additions & 0 deletions
256
...ion/annotations/barriers/accumulators_barriers/accumulators_closed_indicator_painter.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,256 @@ | ||
import 'package:deriv_chart/deriv_chart.dart'; | ||
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/chart_data.dart'; | ||
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/chart_series/series_painter.dart'; | ||
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/models/animation_info.dart'; | ||
import 'package:deriv_chart/src/deriv_chart/chart/helpers/paint_functions/paint_dot.dart'; | ||
import 'package:deriv_chart/src/deriv_chart/chart/helpers/paint_functions/paint_text.dart'; | ||
import 'package:flutter/material.dart'; | ||
|
||
/// Accumulator barriers painter. | ||
class AccumulatorsClosedIndicatorPainter | ||
extends SeriesPainter<AccumulatorsClosedIndicator> { | ||
/// Initializes [AccumulatorsClosedIndicatorPainter]. | ||
AccumulatorsClosedIndicatorPainter(super.series); | ||
|
||
final Paint _linePaint = Paint() | ||
..strokeWidth = 1 | ||
..style = PaintingStyle.stroke; | ||
|
||
final Paint _linePaintFill = Paint() | ||
..strokeWidth = 1 | ||
..style = PaintingStyle.fill; | ||
|
||
final Paint _rectPaint = Paint()..style = PaintingStyle.fill; | ||
|
||
/// Padding between lines. | ||
static const double padding = 4; | ||
|
||
/// Padding between tick and text. | ||
static const double tickTextPadding = 12; | ||
|
||
/// Right margin. | ||
static const double rightMargin = 4; | ||
|
||
@override | ||
void onPaint({ | ||
required Canvas canvas, | ||
required Size size, | ||
required EpochToX epochToX, | ||
required QuoteToY quoteToY, | ||
required AnimationInfo animationInfo, | ||
}) { | ||
final HorizontalBarrierStyle style = | ||
series.style as HorizontalBarrierStyle? ?? theme.horizontalBarrierStyle; | ||
|
||
// Change the barrier color based on the contract status and tick quote. | ||
Color color = theme.base03Color; | ||
if (series.activeContract?.profit != null) { | ||
if (series.activeContract!.profit! > 0) { | ||
color = theme.accentGreenColor; | ||
} else if (series.activeContract!.profit! < 0) { | ||
color = theme.accentRedColor; | ||
} | ||
} | ||
|
||
if (series.exitTick.quote > series.highBarrier || | ||
series.exitTick.quote < series.lowBarrier) { | ||
color = theme.accentRedColor; | ||
} | ||
_linePaint.color = color; | ||
_linePaintFill.color = color; | ||
_rectPaint.color = color.withOpacity(0.08); | ||
|
||
final AccumulatorsClosedIndicator indicator = series; | ||
|
||
final double barrierX = epochToX(indicator.barrierEpoch); | ||
final double hBarrierQuote = indicator.highBarrier; | ||
final double lBarrierQuote = indicator.lowBarrier; | ||
|
||
final Offset highBarrierPosition = Offset( | ||
barrierX, | ||
quoteToY(hBarrierQuote), | ||
); | ||
|
||
final Offset lowBarrierPosition = Offset( | ||
barrierX, | ||
quoteToY(lBarrierQuote), | ||
); | ||
|
||
final Offset exitTickPosition = Offset( | ||
epochToX(indicator.exitTick.epoch), | ||
quoteToY(indicator.exitTick.quote), | ||
); | ||
|
||
// draw the transparent color. | ||
final Rect rect = Rect.fromPoints( | ||
highBarrierPosition, | ||
Offset( | ||
series.barrierEndEpoch != null | ||
? epochToX(series.barrierEndEpoch!) | ||
: size.width, | ||
lowBarrierPosition.dy), | ||
); | ||
canvas.drawRect(rect, _rectPaint); | ||
|
||
const int triangleEdge = 4; | ||
const int triangleHeight = 5; | ||
|
||
final Path upperTrianglePath = Path() | ||
..moveTo( | ||
highBarrierPosition.dx, | ||
highBarrierPosition.dy, | ||
) | ||
..lineTo( | ||
highBarrierPosition.dx + triangleEdge, | ||
highBarrierPosition.dy, | ||
) | ||
..lineTo( | ||
highBarrierPosition.dx, | ||
highBarrierPosition.dy + triangleHeight, | ||
) | ||
..lineTo( | ||
highBarrierPosition.dx + -triangleEdge, | ||
highBarrierPosition.dy, | ||
) | ||
..close(); | ||
|
||
final Path lowerTrianglePath = Path() | ||
..moveTo( | ||
lowBarrierPosition.dx, | ||
lowBarrierPosition.dy, | ||
) | ||
..lineTo( | ||
lowBarrierPosition.dx + triangleEdge, | ||
lowBarrierPosition.dy, | ||
) | ||
..lineTo( | ||
lowBarrierPosition.dx, | ||
lowBarrierPosition.dy - triangleHeight, | ||
) | ||
..lineTo( | ||
lowBarrierPosition.dx + -triangleEdge, | ||
lowBarrierPosition.dy, | ||
) | ||
..close(); | ||
|
||
canvas | ||
..drawLine( | ||
lowBarrierPosition, | ||
Offset( | ||
series.barrierEndEpoch != null | ||
? epochToX(series.barrierEndEpoch!) | ||
: size.width, | ||
lowBarrierPosition.dy), | ||
_linePaint, | ||
) | ||
..drawLine( | ||
highBarrierPosition, | ||
Offset( | ||
series.barrierEndEpoch != null | ||
? epochToX(series.barrierEndEpoch!) | ||
: size.width, | ||
highBarrierPosition.dy), | ||
_linePaint, | ||
) | ||
..drawPath(upperTrianglePath, _linePaint) | ||
..drawPath(lowerTrianglePath, _linePaint) | ||
..drawPath(upperTrianglePath, _linePaintFill) | ||
..drawPath(lowerTrianglePath, _linePaintFill); | ||
|
||
// Draw exit tick position. | ||
paintDot(canvas, exitTickPosition, color); | ||
|
||
// draw dialog | ||
const double dotPadding = 5; | ||
const int dialogTriangleEdge = 6; | ||
const int dialogTriangleHeight = 4; | ||
|
||
final Path dialogTrianglePath = Path() | ||
..moveTo( | ||
exitTickPosition.dx - dotPadding, | ||
exitTickPosition.dy, | ||
) | ||
..lineTo( | ||
exitTickPosition.dx - dotPadding - dialogTriangleHeight, | ||
exitTickPosition.dy - dialogTriangleEdge / 2, | ||
) | ||
..lineTo( | ||
exitTickPosition.dx - dotPadding - dialogTriangleHeight, | ||
exitTickPosition.dy + dialogTriangleEdge / 2, | ||
) | ||
..lineTo( | ||
exitTickPosition.dx - dotPadding, | ||
exitTickPosition.dy, | ||
) | ||
..close(); | ||
|
||
canvas | ||
..drawPath(dialogTrianglePath, _linePaintFill) | ||
..drawPath(dialogTrianglePath, _linePaint); | ||
|
||
if (indicator.activeContract?.profit != null) { | ||
final double profit = indicator.activeContract!.profit!; | ||
final String profitText = | ||
'${profit < 0 ? '' : '+'}${profit.toStringAsFixed(2)}'; | ||
final String currencyText = '${indicator.activeContract?.currency ?? ''}'; | ||
final TextPainter profitPainter = makeTextPainter( | ||
'$profitText $currencyText', | ||
style.textStyle.copyWith( | ||
color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500), | ||
); | ||
|
||
final TextPainter winLossPainter = makeTextPainter( | ||
indicator.activeContract!.profit! > 0 ? 'Won:' : 'Loss:', | ||
style.textStyle.copyWith( | ||
color: Colors.white, fontSize: 10, fontWeight: FontWeight.w400), | ||
); | ||
|
||
final double textHeight = profitPainter.height + winLossPainter.height; | ||
final double textWidth = profitPainter.width; | ||
|
||
final double dialogRightSide = | ||
exitTickPosition.dx - dotPadding - dialogTriangleHeight - padding; | ||
final double dialogLeftSide = dialogRightSide - textWidth; | ||
|
||
final double dialogDownSide = exitTickPosition.dy + textHeight / 2; | ||
final double dialogUpSide = exitTickPosition.dy - textHeight / 2; | ||
|
||
final Rect dialogRect = Rect.fromLTRB( | ||
dialogLeftSide - padding, | ||
dialogUpSide - padding, | ||
dialogRightSide + padding, | ||
dialogDownSide + padding, | ||
); | ||
final RRect rRect = | ||
RRect.fromRectAndRadius(dialogRect, const Radius.circular(4)); | ||
|
||
_rectPaint.color = color.withOpacity(1); | ||
canvas.drawRRect(rRect, _rectPaint); | ||
|
||
final Offset winLossPosition = Offset( | ||
dialogLeftSide + winLossPainter.width / 2, | ||
exitTickPosition.dy - textHeight / 2 + winLossPainter.height / 2, | ||
); | ||
|
||
paintWithTextPainter( | ||
canvas, | ||
painter: winLossPainter, | ||
anchor: winLossPosition, | ||
); | ||
|
||
final Offset profitPosition = Offset( | ||
dialogLeftSide + profitPainter.width / 2, | ||
exitTickPosition.dy - | ||
textHeight / 2 + | ||
profitPainter.height / 2 + | ||
winLossPainter.height, | ||
); | ||
|
||
paintWithTextPainter( | ||
canvas, | ||
painter: profitPainter, | ||
anchor: profitPosition, | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.