From 071e2e1b2d6833a211b13738e5477705825f9ffa Mon Sep 17 00:00:00 2001 From: behnam-deriv <133759298+behnam-deriv@users.noreply.github.com> Date: Wed, 11 Feb 2026 13:20:09 +0800 Subject: [PATCH 1/7] feat: add support for checkpoint line marker, reduced opacity and text parameter for vertical line markers --- lib/deriv_chart.dart | 1 + .../markers/chart_marker.dart | 31 ++- .../digit_marker_icon_painter.dart | 70 +++--- .../tick_marker_icon_painter.dart | 199 +++++++++++------- .../paint_checkpoint_line.dart | 75 +++++++ .../paint_functions/paint_end_line.dart | 53 +++-- .../paint_functions/paint_start_line.dart | 76 ++++--- .../paint_time_marker_utils.dart | 142 +++++++++++-- 8 files changed, 468 insertions(+), 179 deletions(-) create mode 100644 lib/src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart diff --git a/lib/deriv_chart.dart b/lib/deriv_chart.dart index 39df4949e..ae59cabe2 100644 --- a/lib/deriv_chart.dart +++ b/lib/deriv_chart.dart @@ -148,6 +148,7 @@ export 'src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/ac export 'src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/digit_marker_icon_painter.dart'; export 'src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/tick_marker_icon_painter.dart'; export 'src/deriv_chart/chart/helpers/chart.dart'; +export 'src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart'; export 'src/deriv_chart/chart/helpers/paint_functions/paint_end_marker.dart'; export 'src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart'; export 'src/deriv_chart/chart/helpers/paint_functions/paint_start_marker.dart'; diff --git a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart index 17cfd8746..9177a2e82 100644 --- a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart +++ b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart @@ -120,6 +120,14 @@ enum MarkerType { /// It appears as a pill-shaped label with rounded corners containing an icon and the profit/loss /// amount. profitAndLossLabelFixed, + + /// Represents a checkpoint line marker for multi-stage contracts. + /// + /// This marker renders as a vertical dashed line similar to start/end time markers, + /// but without a bottom icon. It can display optional text (e.g., "1", "2") on the + /// line to indicate checkpoint sequence. Used for intermediate evaluation + /// points in contracts like Double Rise/Fall where multiple checkpoints need to be visualized. + checkpointLine, } /// A specialized marker class for displaying various types of markers on a financial chart. @@ -153,12 +161,14 @@ class ChartMarker extends Marker { /// The `color` parameter allows for customization of the marker's color, which can be /// used to visually distinguish different types of markers or to highlight specific markers. /// - /// @param epoch The timestamp of the marker in epoch format (milliseconds since Unix epoch). - /// @param quote The price value of the marker. - /// @param direction The direction in which the marker is pointing (up or down). - /// @param markerType The type of marker, which determines its role and rendering. - /// @param text The text to display on or near the marker. - /// @param color The color of the marker. + /// The [epoch] is the timestamp of the marker in epoch format (milliseconds since Unix epoch). + /// The [quote] is the price value of the marker. + /// The [direction] is the direction in which the marker is pointing (up or down). + /// The [onTap] is an optional callback function invoked when the marker is tapped. + /// The [markerType] determines the type of marker, which determines its role and rendering. + /// The [text] is the text to display on or near the marker. + /// The [color] is the color of the marker. + /// The [hasReducedOpacity] determines whether the marker should be rendered with reduced (0.5) opacity. ChartMarker({ required int epoch, required double quote, @@ -167,6 +177,7 @@ class ChartMarker extends Marker { this.markerType, this.text, this.color, + this.hasReducedOpacity = false, }) : super(epoch: epoch, quote: quote, direction: direction, onTap: onTap); /// The type of marker, which determines its role and how it's rendered on the chart. @@ -195,4 +206,12 @@ class ChartMarker extends Marker { /// If provided, this color overrides the default direction-based coloring. /// If null, uses [style.upColor] for [MarkerDirection.up] or [style.downColor] for [MarkerDirection.down]. final Color? color; + + /// Whether vertical line markers should be rendered with reduced (0.5) opacity. + /// + /// When set to true, marker will be rendered at half opacity. This is useful for indicating markers that represent + /// future or unreached checkpoints in multi-stage contracts. + /// + /// Defaults to false (full opacity). + final bool hasReducedOpacity; } diff --git a/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/digit_marker_icon_painter.dart b/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/digit_marker_icon_painter.dart index c638b4ff3..79fae8afa 100644 --- a/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/digit_marker_icon_painter.dart +++ b/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/digit_marker_icon_painter.dart @@ -42,8 +42,8 @@ class DigitMarkerIconPainter extends MarkerGroupIconPainter { /// when rendering price values. This affects how the last digit is extracted and /// displayed in tick markers. /// - /// @param pipSize The number of decimal places to display for price values. - /// Default is 4, which means prices will be shown with 4 decimal places. + /// The [pipSize] parameter determines the number of decimal places to display for price values. + /// Default is 4, which means prices will be shown with 4 decimal places. DigitMarkerIconPainter({this.pipSize = 4}); /// The number of decimal places to display for price values. @@ -65,14 +65,14 @@ class DigitMarkerIconPainter extends MarkerGroupIconPainter { /// 2. Calculates the opacity based on marker positions /// 3. Delegates the rendering of individual markers to specialized methods /// - /// @param canvas The canvas on which to paint. - /// @param size The size of the drawing area. - /// @param theme The chart's theme, which provides colors and styles. - /// @param markerGroup The group of markers to render. - /// @param epochToX A function that converts epoch timestamps to X coordinates. - /// @param quoteToY A function that converts price quotes to Y coordinates. - /// @param painterProps Properties that affect how markers are rendered. - /// @param animationInfo Information about any ongoing animations. + /// The [canvas] is the canvas on which to paint. + /// The [size] is the size of the drawing area. + /// The [theme] is the chart's theme, which provides colors and styles. + /// The [markerGroup] is the group of markers to render. + /// The [epochToX] is a function that converts epoch timestamps to X coordinates. + /// The [quoteToY] is a function that converts price quotes to Y coordinates. + /// The [painterProps] contains properties that affect how markers are rendered. + /// The [animationInfo] contains information about any ongoing animations. @override void paintMarkerGroup( Canvas canvas, @@ -122,14 +122,15 @@ class DigitMarkerIconPainter extends MarkerGroupIconPainter { /// (start, exit, tick) with their specific visual representations. It delegates /// to specialized methods for each marker type. /// - /// @param canvas The canvas on which to paint. - /// @param size The size of the drawing area. - /// @param theme The chart's theme, which provides colors and styles. - /// @param marker The marker to render. - /// @param anchor The position on the canvas where the marker should be rendered. - /// @param style The style to apply to the marker. - /// @param zoom The current zoom level of the chart. - /// @param opacity The opacity to apply to the marker. + /// The [canvas] is the canvas on which to paint. + /// The [size] is the size of the drawing area. + /// The [theme] is the chart's theme, which provides colors and styles. + /// The [marker] is the marker to render. + /// The [anchor] is the position on the canvas where the marker should be rendered. + /// The [style] is the style to apply to the marker. + /// The [zoom] is the current zoom level of the chart. + /// The [opacity] is the opacity to apply to the marker. + /// The [props] contains additional marker properties that can affect rendering. void _drawMarker( Canvas canvas, Size size, @@ -142,7 +143,8 @@ class DigitMarkerIconPainter extends MarkerGroupIconPainter { MarkerProps props) { switch (marker.markerType) { case MarkerType.startTime: - paintStartLine(canvas, size, marker, anchor, style, theme, zoom, props); + paintStartLine( + canvas, size, marker, anchor, style, theme, zoom, opacity, props); break; case MarkerType.start: @@ -178,13 +180,13 @@ class DigitMarkerIconPainter extends MarkerGroupIconPainter { /// This private method draws a circular marker with the last digit of the price /// displayed inside it. It's used for both regular tick markers and exit markers. /// - /// @param canvas The canvas on which to paint. - /// @param marker The marker to render. - /// @param anchor The position on the canvas where the marker should be rendered. - /// @param style The style to apply to the marker. - /// @param paint The paint object to use for drawing. - /// @param fontColor The color to use for the digit text. - /// @param zoom The current zoom level of the chart. + /// The [canvas] is the canvas on which to paint. + /// The [marker] is the marker to render. + /// The [anchor] is the position on the canvas where the marker should be rendered. + /// The [style] is the style to apply to the marker. + /// The [paint] is the paint object to use for drawing. + /// The [fontColor] is the color to use for the digit text. + /// The [zoom] is the current zoom level of the chart. void _drawTick(Canvas canvas, Marker marker, Offset anchor, MarkerStyle style, Paint paint, Color fontColor, double zoom) { canvas @@ -226,14 +228,14 @@ class DigitMarkerIconPainter extends MarkerGroupIconPainter { /// the contract, with an optional text label. The marker's opacity is adjusted /// based on its position relative to other markers. /// - /// @param canvas The canvas on which to paint. - /// @param size The size of the drawing area. - /// @param theme The chart's theme, which provides colors and styles. - /// @param marker The marker to render. - /// @param anchor The position on the canvas where the marker should be rendered. - /// @param style The style to apply to the marker. - /// @param zoom The current zoom level of the chart. - /// @param opacity The opacity to apply to the marker. + /// The [canvas] is the canvas on which to paint. + /// The [size] is the size of the drawing area. + /// The [theme] is the chart's theme, which provides colors and styles. + /// The [marker] is the marker to render. + /// The [anchor] is the position on the canvas where the marker should be rendered. + /// The [style] is the style to apply to the marker. + /// The [zoom] is the current zoom level of the chart. + /// The [opacity] is the opacity to apply to the marker. void _drawStartPoint( Canvas canvas, Size size, diff --git a/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/tick_marker_icon_painter.dart b/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/tick_marker_icon_painter.dart index a431ea5bf..d8d2192f3 100644 --- a/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/tick_marker_icon_painter.dart +++ b/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/tick_marker_icon_painter.dart @@ -6,6 +6,7 @@ import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/markers/cha import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/markers/marker.dart'; import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/models/animation_info.dart'; import 'package:deriv_chart/src/deriv_chart/chart/helpers/chart.dart'; +import 'package:deriv_chart/src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart'; import 'package:deriv_chart/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart'; import 'package:deriv_chart/src/deriv_chart/chart/helpers/paint_functions/paint_line.dart'; import 'package:deriv_chart/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart'; @@ -50,14 +51,14 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { /// 3. Draws barrier lines connecting significant points /// 4. Delegates the rendering of individual markers to specialized methods /// - /// @param canvas The canvas on which to paint. - /// @param size The size of the drawing area. - /// @param theme The chart's theme, which provides colors and styles. - /// @param markerGroup The group of markers to render. - /// @param epochToX A function that converts epoch timestamps to X coordinates. - /// @param quoteToY A function that converts price quotes to Y coordinates. - /// @param painterProps Properties that affect how markers are rendered. - /// @param animationInfo Information about any ongoing animations. + /// The [canvas] is the canvas on which to paint. + /// The [size] is the size of the drawing area. + /// The [theme] is the chart's theme, which provides colors and styles. + /// The [markerGroup] is the group of markers to render. + /// The [epochToX] is a function that converts epoch timestamps to X coordinates. + /// The [quoteToY] is a function that converts price quotes to Y coordinates. + /// The [painterProps] contains properties that affect how markers are rendered. + /// The [animationInfo] contains information about any ongoing animations. @override void paintMarkerGroup( Canvas canvas, @@ -128,6 +129,10 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { continue; } + // Calculate marker-specific opacity: apply reduced opacity if specified + final double markerOpacity = + marker.hasReducedOpacity ? opacity * 0.5 : opacity; + _drawMarker( canvas, size, @@ -135,9 +140,9 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { marker, center, markerGroup.style, - painterProps.zoom, + 1.2, painterProps.granularity, - opacity, + markerOpacity, paint, animationInfo, markerGroup.id, @@ -156,13 +161,15 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { /// - A solid line from the entry tick to the end marker /// - A dashed horizontal line from the end marker to the chart's right edge /// - /// @param canvas The canvas on which to paint. - /// @param size The size of the drawing area. - /// @param points A map of marker types to their positions on the canvas. - /// @param markerGroup The group of markers to render. - /// @param style The style to apply to the barriers. - /// @param opacity The opacity to apply to the barriers. - /// @param painterProps Properties that affect how barriers are rendered. + /// The [canvas] is the canvas on which to paint. + /// The [size] is the size of the drawing area. + /// The [points] is a map of marker types to their positions on the canvas. + /// The [markerGroup] is the group of markers to render. + /// The [style] is the style to apply to the barriers. + /// The [theme] is the chart theme providing color schemes and styling. + /// The [opacity] is the opacity to apply to the barriers. + /// The [painterProps] contains properties that affect how barriers are rendered. + /// The [paint] is the paint object used for rendering. void _drawBarriers( Canvas canvas, Size size, @@ -278,17 +285,19 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { /// (start, entry, tick, exit, end) with their specific visual representations. /// It delegates to specialized methods for each marker type. /// - /// @param canvas The canvas on which to paint. - /// @param size The size of the drawing area. - /// @param theme The chart's theme, which provides colors and styles. - /// @param marker The marker to render. - /// @param anchor The position on the canvas where the marker should be rendered. - /// @param style The style to apply to the marker. - /// @param zoom The current zoom level of the chart. - /// @param opacity The opacity to apply to the marker. - /// @param animationInfo Information about any ongoing animations. - /// @param markerGroupId The ID of the marker group for animation tracking. - /// @param markerGroup The marker group containing all related markers for this contract. + /// The [canvas] is the canvas on which to paint. + /// The [size] is the size of the drawing area. + /// The [theme] is the chart's theme, which provides colors and styles. + /// The [marker] is the marker to render. + /// The [anchor] is the position on the canvas where the marker should be rendered. + /// The [style] is the style to apply to the marker. + /// The [zoom] is the current zoom level of the chart. + /// The [granularity] is the time interval between data points. + /// The [opacity] is the opacity to apply to the marker. + /// The [paint] is the paint object used for rendering. + /// The [animationInfo] contains information about any ongoing animations. + /// The [markerGroupId] is the ID of the marker group for animation tracking. + /// The [markerGroup] is the marker group containing all related markers for this contract. void _drawMarker( Canvas canvas, Size size, @@ -313,7 +322,7 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { break; case MarkerType.startTime: paintStartLine(canvas, size, marker, anchor, style, theme, zoom, - markerGroup.props); + opacity, markerGroup.props); break; case MarkerType.start: _drawStartPoint( @@ -321,10 +330,10 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { break; case MarkerType.entry: case MarkerType.entrySpot: - _drawSpotPoint(canvas, marker, anchor, style, theme, zoom, opacity); + _drawEntrySpot(canvas, marker, anchor, style, theme, zoom, opacity); break; case MarkerType.exitSpot: - _drawSpotPoint(canvas, marker, anchor, style, theme, zoom, opacity); + _drawExitSpot(canvas, marker, anchor, style, theme, zoom, opacity); break; case MarkerType.exit: canvas.drawCircle( @@ -342,7 +351,11 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { break; case MarkerType.exitTime: paintEndLine(canvas, size, marker, anchor, style, theme, zoom, - markerGroup.props); + opacity, markerGroup.props); + break; + case MarkerType.checkpointLine: + paintCheckpointLine(canvas, size, marker, anchor, style, theme, zoom, + opacity, markerGroup.props); break; case MarkerType.startTimeCollapsed: _drawCollapsedTimeLine( @@ -506,10 +519,11 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { /// with smooth interpolation between updates using currentTickPercent from AnimationInfo. /// It takes granularity into account for accurate timing calculations. /// - /// @param markerGroup The marker group containing contract information. - /// @param animationInfo Animation information containing currentTickPercent. - /// @param granularity The time interval between data points in milliseconds. - /// @return The animated remaining duration as a value between 0.0 and 1.0. + /// The [markerGroup] is the marker group containing contract information. + /// The [animationInfo] contains animation information including currentTickPercent. + /// The [granularity] is the time interval between data points in milliseconds. + /// + /// Returns the animated remaining duration as a value between 0.0 and 1.0. double _calculateAnimatedRemainingDuration( MarkerGroup markerGroup, AnimationInfo animationInfo, @@ -570,16 +584,16 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { /// The marker includes a background circle, progress arc, and a directional /// arrow icon in the center. /// - /// @param canvas The canvas on which to paint. - /// @param theme The chart's theme, which provides colors and styles. - /// @param marker The marker object containing direction and progress. - /// @param anchor The position on the canvas where the marker should be rendered. - /// @param style The style to apply to the marker. - /// @param zoom The current zoom level of the chart. - /// @param opacity The opacity to apply to the marker. - /// @param animationInfo Information about any ongoing animations. - /// @param markerGroupId The ID of the marker group for animation tracking. - /// @param markerGroup The marker group containing all related markers for this contract. + /// The [canvas] is the canvas on which to paint. + /// The [marker] is the marker object containing direction and progress. + /// The [anchor] is the position on the canvas where the marker should be rendered. + /// The [style] is the style to apply to the marker. + /// The [zoom] is the current zoom level of the chart. + /// The [granularity] is the time interval between data points. + /// The [opacity] is the opacity to apply to the marker. + /// The [animationInfo] contains information about any ongoing animations. + /// The [markerGroupId] is the ID of the marker group for animation tracking. + /// The [markerGroup] is the marker group containing all related markers for this contract. void _drawContractMarker( Canvas canvas, ChartMarker marker, @@ -694,11 +708,11 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { /// Draws a diagonal arrow icon inside the contract marker. /// - /// @param canvas The canvas on which to paint. - /// @param center The center position of the arrow. - /// @param marker The marker object containing direction information. - /// @param color The color of the arrow. - /// @param zoom The current zoom level of the chart. + /// The [canvas] is the canvas on which to paint. + /// The [center] is the center position of the arrow. + /// The [marker] is the marker object containing direction information. + /// The [color] is the color of the arrow. + /// The [zoom] is the current zoom level of the chart. void _drawArrowIcon(Canvas canvas, Offset center, ChartMarker marker, Color color, double zoom) { final double dir = marker.direction == MarkerDirection.up ? 1 : -1; @@ -746,10 +760,10 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { /// This private method draws a small circular dot representing a price tick. /// Tick points are used to visualize individual price updates in the contract. /// - /// @param canvas The canvas on which to paint. - /// @param anchor The position on the canvas where the tick point should be rendered. - /// @param paint The paint object to use for drawing. - /// @param zoom The current zoom level of the chart. + /// The [canvas] is the canvas on which to paint. + /// The [anchor] is the position on the canvas where the tick point should be rendered. + /// The [paint] is the paint object to use for drawing. + /// The [zoom] is the current zoom level of the chart. void _drawTickPoint(Canvas canvas, Offset anchor, Paint paint, double zoom) { canvas.drawCircle( anchor, @@ -765,13 +779,14 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { /// the price and time at which the contract started. It consists of an /// outer circle with marker direction color and an inner white circle. /// - /// @param canvas The canvas on which to paint. - /// @param marker The marker object containing direction information. - /// @param anchor The position on the canvas where the entry point should be rendered. - /// @param style The style to apply to the marker. - /// @param zoom The current zoom level of the chart. - /// @param opacity The opacity to apply to the entry point. - void _drawSpotPoint(Canvas canvas, ChartMarker marker, Offset anchor, + /// The [canvas] is the canvas on which to paint. + /// The [marker] is the marker object containing direction information. + /// The [anchor] is the position on the canvas where the entry point should be rendered. + /// The [style] is the style to apply to the marker. + /// The [theme] is the chart theme providing color schemes. + /// The [zoom] is the current zoom level of the chart. + /// The [opacity] is the opacity to apply to the entry point. + void _drawEntrySpot(Canvas canvas, ChartMarker marker, Offset anchor, MarkerStyle style, ChartTheme theme, double zoom, double opacity) { // Draw white filled circle final Paint fillPaint = Paint() @@ -792,20 +807,52 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { canvas.drawCircle(anchor, 3 * zoom, strokePaint); } + /// Draws an exit spot marker as a filled circle. + /// + /// The exit spot is rendered as a solid filled circle with a color determined by: + /// - The marker's explicit color if provided (marker.color) + /// - Or the direction-based color from the theme (green for up, red for down) + /// + /// This is used for checkpoint markers in multi-stage contracts like Double Rise/Fall, + /// where each checkpoint has an exit spot indicating whether the checkpoint passed or failed. + /// + /// The [canvas] is the canvas on which to paint. + /// The [marker] is the chart marker containing direction and optional color. + /// The [anchor] is the position where the exit spot should be drawn. + /// The [style] is the marker style (unused but kept for signature consistency). + /// The [theme] is the chart theme providing direction-based colors. + /// The [zoom] is the zoom factor to scale the circle radius. + /// The [opacity] is the opacity to apply to the marker. + void _drawExitSpot(Canvas canvas, ChartMarker marker, Offset anchor, + MarkerStyle style, ChartTheme theme, double zoom, double opacity) { + // Determine color from marker.color or direction + final Color markerColor = marker.color ?? + (marker.direction == MarkerDirection.up + ? theme.markerStyle.upColorProminent + : theme.markerStyle.downColorProminent); + + // Draw filled circle + final Paint fillPaint = Paint() + ..color = markerColor.withOpacity(opacity) + ..style = PaintingStyle.fill; + + canvas.drawCircle(anchor, 3 * zoom, fillPaint); + } + /// Renders the starting point of a tick contract. /// /// This private method draws a location pin marker at the starting point of /// the contract, with an optional text label. The marker's opacity is adjusted /// based on its position relative to other markers. /// - /// @param canvas The canvas on which to paint. - /// @param size The size of the drawing area. - /// @param theme The chart's theme, which provides colors and styles. - /// @param marker The marker to render. - /// @param anchor The position on the canvas where the marker should be rendered. - /// @param style The style to apply to the marker. - /// @param zoom The current zoom level of the chart. - /// @param opacity The opacity to apply to the marker. + /// The [canvas] is the canvas on which to paint. + /// The [size] is the size of the drawing area. + /// The [theme] is the chart's theme, which provides colors and styles. + /// The [marker] is the marker to render. + /// The [anchor] is the position on the canvas where the marker should be rendered. + /// The [style] is the style to apply to the marker. + /// The [zoom] is the current zoom level of the chart. + /// The [opacity] is the opacity to apply to the marker. void _drawStartPoint( Canvas canvas, Size size, @@ -852,12 +899,12 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { /// This private method draws a circular marker representing the end point /// of the contract. The color is determined by the marker direction. /// - /// @param canvas The canvas on which to paint. - /// @param marker The marker object containing direction information. - /// @param anchor The position on the canvas where the end point should be rendered. - /// @param style The style to apply to the marker. - /// @param zoom The current zoom level of the chart. - /// @param opacity The opacity to apply to the end point. + /// The [canvas] is the canvas on which to paint. + /// The [marker] is the marker object containing direction information. + /// The [anchor] is the position on the canvas where the end point should be rendered. + /// The [style] is the style to apply to the marker. + /// The [zoom] is the current zoom level of the chart. + /// The [opacity] is the opacity to apply to the end point. void _drawEndPoint(Canvas canvas, ChartMarker marker, Offset anchor, MarkerStyle style, double zoom, double opacity) { final Paint paint = Paint() diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart new file mode 100644 index 000000000..821414e17 --- /dev/null +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart @@ -0,0 +1,75 @@ +import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart'; +import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/markers/marker.dart'; +import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/markers/marker_props.dart'; +import 'package:deriv_chart/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart'; +import 'package:deriv_chart/src/theme/chart_theme.dart'; +import 'package:deriv_chart/src/theme/painting_styles/marker_style.dart'; +import 'package:flutter/material.dart'; + +/// Renders a vertical dashed line with optional text to indicate a checkpoint. +/// +/// This function draws a vertical dashed line at the specified horizontal position, +/// similar to start/exit time markers, but without a bottom icon. If the marker has +/// text, it renders the text at the anchor position. +/// +/// This marker type is used for intermediate checkpoints in multi-stage contracts +/// (e.g., Double Rise/Fall) where multiple evaluation points need to be visualized +/// along the timeline. +/// +/// The function performs two main rendering operations: +/// 1. Draws a vertical dashed line using the `paintVerticalTimeLine` helper function +/// 2. If text is provided in the marker, renders a text label at the anchor position +/// +/// The vertical line uses the color determined by the marker's direction or explicit color, +/// and can optionally be rendered with reduced opacity if specified in the marker properties. +/// +/// The [canvas] is the canvas on which to paint the line and text. +/// The [size] is the size of the drawing area, used to determine the vertical extent of the line. +/// The [marker] is the chart marker containing information like text to display and direction. +/// The [anchor] is the position on the canvas where the line should be anchored. +/// The [style] is the marker style, which provides colors and styling information. +/// The [theme] is the chart theme, which provides color schemes and styling. +/// The [zoom] is the zoom factor to apply to text size and other dimensions. +/// The [opacity] is the opacity to apply to the line and text. +/// The [props] contains additional marker properties that can affect rendering. +void paintCheckpointLine( + Canvas canvas, + Size size, + ChartMarker marker, + Offset anchor, + MarkerStyle style, + ChartTheme theme, + double zoom, + double opacity, + MarkerProps props, +) { + // Determine marker color based on marker.color or marker direction + final Color markerColor = marker.color ?? + (marker.direction == MarkerDirection.up + ? theme.markerStyle.upColorProminent + : theme.markerStyle.downColorProminent); + + final Color lineColor = markerColor.withOpacity(opacity); + + // Render text label inline at the anchor level if provided (e.g., "1", "2") + if (marker.text != null && marker.text!.isNotEmpty) { + TimeMarkerPainters.paintVerticalLineWithText( + canvas, + size, + marker.text!, + anchor, + lineColor, + zoom, + dashed: true, + ); + } else { + // Draw full vertical dashed line from near the top to near the bottom of the chart + TimeMarkerPainters.paintVerticalTimeLine( + canvas, + size, + anchor.dx, + color: lineColor, + dashed: true, + ); + } +} diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart index 0a2d06538..6ae5caaa0 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart @@ -20,12 +20,15 @@ import 'package:flutter/material.dart'; /// The vertical line uses the background color from the provided style, and the icon /// is styled according to the marker style with appropriate scaling based on the zoom factor. /// -/// @param canvas The canvas on which to paint the line and icon. -/// @param size The size of the drawing area, used to determine the vertical extent of the line. -/// @param marker The chart marker (kept for signature parity with start line painter). -/// @param anchor The position on the canvas where the line should be anchored. -/// @param style The marker style, which provides colors and icon styling information. -/// @param zoom The zoom factor to apply to icon size and other dimensions. +/// The [canvas] is the canvas on which to paint the line and icon. +/// The [size] is the size of the drawing area, used to determine the vertical extent of the line. +/// The [marker] is the chart marker (kept for signature parity with start line painter). +/// The [anchor] is the position on the canvas where the line should be anchored. +/// The [style] is the marker style, which provides colors and icon styling information. +/// The [theme] is the chart theme, which provides color schemes and styling. +/// The [zoom] is the zoom factor to apply to icon size and other dimensions. +/// The [opacity] is the opacity to apply to the line and icon. +/// The [props] contains additional marker properties that can affect rendering. void paintEndLine( Canvas canvas, Size size, @@ -34,6 +37,7 @@ void paintEndLine( MarkerStyle style, ChartTheme theme, double zoom, + double opacity, MarkerProps props, ) { // Determine marker color based on marker.color or marker direction @@ -41,25 +45,38 @@ void paintEndLine( (marker.direction == MarkerDirection.up ? theme.markerStyle.upColorProminent : theme.markerStyle.downColorProminent); - final bool isDashed = props.isRunning; - // Draw the vertical line from near the top of the chart to near the bottom. - // Use dashed style while running, otherwise paint as a solid line. - TimeMarkerPainters.paintVerticalTimeLine( - canvas, - size, - anchor.dx, - color: markerColor, - dashed: isDashed, - ); + final Color lineColor = markerColor.withOpacity(opacity); + + // If marker has text, render it inline at the anchor level + if (marker.text != null && marker.text!.isNotEmpty) { + TimeMarkerPainters.paintVerticalLineWithText( + canvas, + size, + marker.text!, + anchor, + lineColor, + zoom, + dashed: true, + ); + } else { + // Draw full vertical line from near the top of the chart to near the bottom + TimeMarkerPainters.paintVerticalTimeLine( + canvas, + size, + anchor.dx, + color: lineColor, + dashed: true, + ); + } - // Render the end icon (flag) at the bottom of the line following MarkerStyle. + // Render the end icon (flag) at the bottom of the line following MarkerStyle TimeMarkerPainters.paintBottomIcon( canvas, size, anchor.dx, style.endTimeIcon, zoom, - markerColor, + lineColor, ); } diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart index 3e6d14737..ed6477282 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart @@ -21,36 +21,62 @@ import 'package:flutter/material.dart'; /// (if present) is styled according to the marker style with appropriate scaling /// based on the zoom factor. /// -/// @param canvas The canvas on which to paint the line and text. -/// @param size The size of the drawing area, used to determine the vertical extent of the line. -/// @param marker The chart marker containing information like text to display. -/// @param anchor The position on the canvas where the line should be anchored. -/// @param style The marker style, which provides colors and text styling information. -/// @param zoom The zoom factor to apply to text size and other dimensions. -void paintStartLine(Canvas canvas, Size size, ChartMarker marker, Offset anchor, - MarkerStyle style, ChartTheme theme, double zoom, MarkerProps props) { +/// The [canvas] is the canvas on which to paint the line and text. +/// The [size] is the size of the drawing area, used to determine the vertical extent of the line. +/// The [marker] is the chart marker containing information like text to display. +/// The [anchor] is the position on the canvas where the line should be anchored. +/// The [style] is the marker style, which provides colors and text styling information. +/// The [theme] is the chart theme, which provides color schemes and styling. +/// The [zoom] is the zoom factor to apply to text size and other dimensions. +/// The [opacity] is the opacity to apply to the line and text. +/// The [props] contains additional marker properties that can affect rendering. +void paintStartLine( + Canvas canvas, + Size size, + ChartMarker marker, + Offset anchor, + MarkerStyle style, + ChartTheme theme, + double zoom, + double opacity, + MarkerProps props) { // Determine marker color based on marker.color or marker direction final Color markerColor = marker.color ?? (marker.direction == MarkerDirection.up ? theme.markerStyle.upColorProminent : theme.markerStyle.downColorProminent); - // Draw a vertical dashed line from near the top of the chart to near the bottom. - TimeMarkerPainters.paintVerticalTimeLine( - canvas, - size, - anchor.dx, - color: markerColor, - dashed: true, - ); + final Color lineColor = markerColor.withOpacity(opacity); - // Render the start icon at the bottom of the line following MarkerStyle. - TimeMarkerPainters.paintBottomIcon( - canvas, - size, - anchor.dx, - style.startTimeIcon, - zoom, - markerColor, - ); + // If marker has text, render it inline at the anchor level + if (marker.text != null && marker.text!.isNotEmpty) { + TimeMarkerPainters.paintVerticalLineWithText( + canvas, + size, + marker.text!, + anchor, + lineColor, + zoom, + dashed: true, + ); + } else { + // Draw full vertical dashed line from near the top of the chart to near the bottom + TimeMarkerPainters.paintVerticalTimeLine( + canvas, + size, + anchor.dx, + color: lineColor, + dashed: true, + ); + + // Render the start icon at the bottom of the line following MarkerStyle + TimeMarkerPainters.paintBottomIcon( + canvas, + size, + anchor.dx, + style.startTimeIcon, + zoom, + lineColor, + ); + } } diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart index 915129edf..e72f80adb 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart @@ -11,6 +11,10 @@ class TimeMarkerPainters { /// /// When [dashed] is true, draws a dashed line using [dashWidth] and [dashSpace]. /// Otherwise, draws a solid line with [strokeWidth]. + /// + /// If [gapHeight] and [gapOffset] are provided, creates a gap in the line: + /// - [gapHeight]: The height of the gap in pixels + /// - [gapOffset]: The Y position where the gap starts (top of the gap) static void paintVerticalTimeLine( Canvas canvas, Size size, @@ -22,31 +26,129 @@ class TimeMarkerPainters { double bottomPadding = 28, double dashWidth = 2, double dashSpace = 2, + double? gapHeight, + double? gapOffset, }) { - if (dashed) { - paintVerticalDashedLine( - canvas, - x, - topPadding, - size.height - bottomPadding, - color, - strokeWidth, - dashWidth: dashWidth, - dashSpace: dashSpace, - ); - } else { - final Paint paint = Paint() - ..color = color - ..strokeWidth = strokeWidth; + final double lineStartY = topPadding; + final double lineEndY = size.height - bottomPadding; + + // If gap parameters are provided, draw line in two segments + if (gapHeight != null && gapOffset != null) { + final double gapTop = gapOffset; + final double gapBottom = gapOffset + gapHeight; + + // Draw top segment + if (dashed) { + paintVerticalDashedLine( + canvas, + x, + lineStartY, + gapTop, + color, + strokeWidth, + dashWidth: dashWidth, + dashSpace: dashSpace, + ); + } else { + final Paint paint = Paint() + ..color = color + ..strokeWidth = strokeWidth; + canvas.drawLine(Offset(x, lineStartY), Offset(x, gapTop), paint); + } - canvas.drawLine( - Offset(x, topPadding), - Offset(x, size.height - bottomPadding), - paint, - ); + // Draw bottom segment + if (dashed) { + paintVerticalDashedLine( + canvas, + x, + gapBottom, + lineEndY, + color, + strokeWidth, + dashWidth: dashWidth, + dashSpace: dashSpace, + ); + } else { + final Paint paint = Paint() + ..color = color + ..strokeWidth = strokeWidth; + canvas.drawLine(Offset(x, gapBottom), Offset(x, lineEndY), paint); + } + } else { + // Draw full line without gap + if (dashed) { + paintVerticalDashedLine( + canvas, + x, + lineStartY, + lineEndY, + color, + strokeWidth, + dashWidth: dashWidth, + dashSpace: dashSpace, + ); + } else { + final Paint paint = Paint() + ..color = color + ..strokeWidth = strokeWidth; + canvas.drawLine(Offset(x, lineStartY), Offset(x, lineEndY), paint); + } } } + /// Paints a vertical line with text label centered in a gap at the anchor level. + /// + /// The [canvas] is the canvas on which to paint. + /// The [size] is the size of the drawing area. + /// The [text] is the text to display in the gap. + /// The [anchor] is the position where the gap should start (anchor level). + /// The [color] is the color for both the line and text. + /// The [zoom] is the zoom factor for text sizing. + /// The [dashed] parameter determines whether the line should be dashed. + static void paintVerticalLineWithText( + Canvas canvas, + Size size, + String text, + Offset anchor, + Color color, + double zoom, { + required bool dashed, + }) { + final TextPainter textPainter = TextPainter( + text: TextSpan( + text: text, + style: TextStyle( + color: color, + fontSize: 12 * zoom, + fontWeight: FontWeight.bold, + ), + ), + textDirection: TextDirection.ltr, + )..layout(); + + // Add padding around text and center it vertically within the gap + final double verticalPadding = 4 * zoom; + final double gapHeight = textPainter.height + (verticalPadding * 2); + + // Center text within the gap + final double textY = anchor.dy + (gapHeight - textPainter.height) / 2; + final double textX = anchor.dx - textPainter.width / 2; + + // Draw vertical line with gap starting at barrier level + paintVerticalTimeLine( + canvas, + size, + anchor.dx, + color: color, + dashed: dashed, + gapHeight: gapHeight, + gapOffset: anchor.dy, + ); + + // Paint the text in the gap + textPainter.paint(canvas, Offset(textX, textY)); + } + /// Paints an [icon] centered at the bottom (a few pixels above) of the chart at [x]. static void paintBottomIcon( Canvas canvas, From 3db9e6989cb9e59afa9595bd2541a4bb5e7b65ff Mon Sep 17 00:00:00 2001 From: behnam-deriv <133759298+behnam-deriv@users.noreply.github.com> Date: Wed, 11 Feb 2026 15:06:37 +0800 Subject: [PATCH 2/7] feat: add checkpointLineCollapsed marker & move the marker text at the bottom of vertical lines if provided --- .../markers/chart_marker.dart | 7 + .../tick_marker_icon_painter.dart | 11 ++ .../paint_checkpoint_line.dart | 31 ++-- .../paint_functions/paint_end_line.dart | 40 ++--- .../paint_functions/paint_start_line.dart | 73 ++++---- .../paint_time_marker_utils.dart | 168 ++++++------------ 6 files changed, 132 insertions(+), 198 deletions(-) diff --git a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart index 9177a2e82..9d74261a4 100644 --- a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart +++ b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart @@ -128,6 +128,13 @@ enum MarkerType { /// line to indicate checkpoint sequence. Used for intermediate evaluation /// points in contracts like Double Rise/Fall where multiple checkpoints need to be visualized. checkpointLine, + + /// Represents a compact solid checkpoint vertical line. + /// + /// Draws a short, solid vertical line segment to indicate + /// a checkpoint time in a condensed layout. Similar to startTimeCollapsed and exitTimeCollapsed, + /// but used for intermediate checkpoints in multi-stage contracts. + checkpointLineCollapsed, } /// A specialized marker class for displaying various types of markers on a financial chart. diff --git a/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/tick_marker_icon_painter.dart b/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/tick_marker_icon_painter.dart index d8d2192f3..4eeef5524 100644 --- a/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/tick_marker_icon_painter.dart +++ b/lib/src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/tick_marker_icon_painter.dart @@ -379,6 +379,17 @@ class TickMarkerIconPainter extends MarkerGroupIconPainter { opacity, ); break; + case MarkerType.checkpointLineCollapsed: + _drawCollapsedTimeLine( + canvas, + marker, + anchor, + style, + theme, + zoom, + opacity, + ); + break; case MarkerType.profitAndLossLabel: _drawProfitAndLossLabel( canvas, diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart index 821414e17..f733ef2dc 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_checkpoint_line.dart @@ -10,7 +10,7 @@ import 'package:flutter/material.dart'; /// /// This function draws a vertical dashed line at the specified horizontal position, /// similar to start/exit time markers, but without a bottom icon. If the marker has -/// text, it renders the text at the anchor position. +/// text, it renders the text at the bottom of the line. /// /// This marker type is used for intermediate checkpoints in multi-stage contracts /// (e.g., Double Rise/Fall) where multiple evaluation points need to be visualized @@ -18,7 +18,7 @@ import 'package:flutter/material.dart'; /// /// The function performs two main rendering operations: /// 1. Draws a vertical dashed line using the `paintVerticalTimeLine` helper function -/// 2. If text is provided in the marker, renders a text label at the anchor position +/// 2. If text is provided in the marker, renders a text label at the bottom of the line /// /// The vertical line uses the color determined by the marker's direction or explicit color, /// and can optionally be rendered with reduced opacity if specified in the marker properties. @@ -51,25 +51,24 @@ void paintCheckpointLine( final Color lineColor = markerColor.withOpacity(opacity); - // Render text label inline at the anchor level if provided (e.g., "1", "2") + // Draw full vertical dashed line from near the top to near the bottom of the chart + TimeMarkerPainters.paintVerticalTimeLine( + canvas, + size, + anchor.dx, + color: lineColor, + dashed: true, + ); + + // Render text label at the bottom if provided (e.g., "1", "2") if (marker.text != null && marker.text!.isNotEmpty) { - TimeMarkerPainters.paintVerticalLineWithText( + TimeMarkerPainters.paintBottomText( canvas, size, + anchor.dx, marker.text!, - anchor, - lineColor, zoom, - dashed: true, - ); - } else { - // Draw full vertical dashed line from near the top to near the bottom of the chart - TimeMarkerPainters.paintVerticalTimeLine( - canvas, - size, - anchor.dx, - color: lineColor, - dashed: true, + lineColor, ); } } diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart index 6ae5caaa0..b29967d91 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart @@ -11,11 +11,11 @@ import 'package:flutter/material.dart'; /// This function draws a vertical dashed line at the specified horizontal position, /// extending from near the top of the chart to near the bottom. The line visually /// marks the end time of a contract or trade on a financial chart. It also renders -/// a flag icon near the bottom of the line. +/// a flag icon near the bottom of the line or displays text if provided in the marker. /// /// The function performs two main rendering operations: /// 1. Draws a vertical dashed line using the `paintVerticalDashedLine` helper function -/// 2. Renders a flag icon near the bottom of the chart +/// 2. Renders a flag icon near the bottom of the chart or text if provided in the marker /// /// The vertical line uses the background color from the provided style, and the icon /// is styled according to the marker style with appropriate scaling based on the zoom factor. @@ -48,35 +48,33 @@ void paintEndLine( final Color lineColor = markerColor.withOpacity(opacity); - // If marker has text, render it inline at the anchor level + // Draw full vertical line from near the top of the chart to near the bottom + TimeMarkerPainters.paintVerticalTimeLine( + canvas, + size, + anchor.dx, + color: lineColor, + dashed: true, + ); + + // Render text at the bottom if provided, otherwise render the flag icon if (marker.text != null && marker.text!.isNotEmpty) { - TimeMarkerPainters.paintVerticalLineWithText( + TimeMarkerPainters.paintBottomText( canvas, size, + anchor.dx, marker.text!, - anchor, - lineColor, zoom, - dashed: true, + lineColor, ); } else { - // Draw full vertical line from near the top of the chart to near the bottom - TimeMarkerPainters.paintVerticalTimeLine( + TimeMarkerPainters.paintBottomIcon( canvas, size, anchor.dx, - color: lineColor, - dashed: true, + style.endTimeIcon, + zoom, + lineColor, ); } - - // Render the end icon (flag) at the bottom of the line following MarkerStyle - TimeMarkerPainters.paintBottomIcon( - canvas, - size, - anchor.dx, - style.endTimeIcon, - zoom, - lineColor, - ); } diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart index ed6477282..a560d9314 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart @@ -6,29 +6,29 @@ import 'package:deriv_chart/src/theme/chart_theme.dart'; import 'package:deriv_chart/src/theme/painting_styles/marker_style.dart'; import 'package:flutter/material.dart'; -/// Renders a vertical dashed line with optional text to indicate the start time of a contract. +/// Renders a vertical dashed line with a stopwatch icon to indicate the start time of a contract. /// /// This function draws a vertical dashed line at the specified horizontal position, /// extending from near the top of the chart to near the bottom. The line visually -/// marks the starting time of a contract or trade on a financial chart. If the marker -/// has text, it also renders a text label near the bottom of the line. +/// marks the starting time of a contract or trade on a financial chart. A stopwatch +/// icon is rendered at the bottom of the line. /// /// The function performs two main rendering operations: -/// 1. Draws a vertical dashed line using the `paintVerticalDashedLine` helper function -/// 2. If text is provided in the marker, renders a text label near the bottom of the chart +/// 1. Draws a vertical dashed line using the `paintVerticalTimeLine` helper function +/// 2. Renders a stopwatch icon at the bottom of the chart /// -/// The vertical line uses the background color from the provided style, and the text -/// (if present) is styled according to the marker style with appropriate scaling -/// based on the zoom factor. +/// The vertical line uses the color determined by the marker's direction or explicit color, +/// and the icon is styled according to the marker style with appropriate scaling based +/// on the zoom factor. /// -/// The [canvas] is the canvas on which to paint the line and text. +/// The [canvas] is the canvas on which to paint the line and icon. /// The [size] is the size of the drawing area, used to determine the vertical extent of the line. -/// The [marker] is the chart marker containing information like text to display. +/// The [marker] is the chart marker (kept for signature parity with other line painters). /// The [anchor] is the position on the canvas where the line should be anchored. -/// The [style] is the marker style, which provides colors and text styling information. +/// The [style] is the marker style, which provides colors and icon styling information. /// The [theme] is the chart theme, which provides color schemes and styling. -/// The [zoom] is the zoom factor to apply to text size and other dimensions. -/// The [opacity] is the opacity to apply to the line and text. +/// The [zoom] is the zoom factor to apply to icon size and other dimensions. +/// The [opacity] is the opacity to apply to the line and icon. /// The [props] contains additional marker properties that can affect rendering. void paintStartLine( Canvas canvas, @@ -48,35 +48,22 @@ void paintStartLine( final Color lineColor = markerColor.withOpacity(opacity); - // If marker has text, render it inline at the anchor level - if (marker.text != null && marker.text!.isNotEmpty) { - TimeMarkerPainters.paintVerticalLineWithText( - canvas, - size, - marker.text!, - anchor, - lineColor, - zoom, - dashed: true, - ); - } else { - // Draw full vertical dashed line from near the top of the chart to near the bottom - TimeMarkerPainters.paintVerticalTimeLine( - canvas, - size, - anchor.dx, - color: lineColor, - dashed: true, - ); + // Draw full vertical dashed line from near the top of the chart to near the bottom + TimeMarkerPainters.paintVerticalTimeLine( + canvas, + size, + anchor.dx, + color: lineColor, + dashed: true, + ); - // Render the start icon at the bottom of the line following MarkerStyle - TimeMarkerPainters.paintBottomIcon( - canvas, - size, - anchor.dx, - style.startTimeIcon, - zoom, - lineColor, - ); - } + // Render the start icon (stopwatch) at the bottom of the line following MarkerStyle + TimeMarkerPainters.paintBottomIcon( + canvas, + size, + anchor.dx, + style.startTimeIcon, + zoom, + lineColor, + ); } diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart index e72f80adb..b293da25e 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart @@ -11,10 +11,6 @@ class TimeMarkerPainters { /// /// When [dashed] is true, draws a dashed line using [dashWidth] and [dashSpace]. /// Otherwise, draws a solid line with [strokeWidth]. - /// - /// If [gapHeight] and [gapOffset] are provided, creates a gap in the line: - /// - [gapHeight]: The height of the gap in pixels - /// - [gapOffset]: The Y position where the gap starts (top of the gap) static void paintVerticalTimeLine( Canvas canvas, Size size, @@ -26,158 +22,94 @@ class TimeMarkerPainters { double bottomPadding = 28, double dashWidth = 2, double dashSpace = 2, - double? gapHeight, - double? gapOffset, }) { final double lineStartY = topPadding; final double lineEndY = size.height - bottomPadding; - // If gap parameters are provided, draw line in two segments - if (gapHeight != null && gapOffset != null) { - final double gapTop = gapOffset; - final double gapBottom = gapOffset + gapHeight; - - // Draw top segment - if (dashed) { - paintVerticalDashedLine( - canvas, - x, - lineStartY, - gapTop, - color, - strokeWidth, - dashWidth: dashWidth, - dashSpace: dashSpace, - ); - } else { - final Paint paint = Paint() - ..color = color - ..strokeWidth = strokeWidth; - canvas.drawLine(Offset(x, lineStartY), Offset(x, gapTop), paint); - } - - // Draw bottom segment - if (dashed) { - paintVerticalDashedLine( - canvas, - x, - gapBottom, - lineEndY, - color, - strokeWidth, - dashWidth: dashWidth, - dashSpace: dashSpace, - ); - } else { - final Paint paint = Paint() - ..color = color - ..strokeWidth = strokeWidth; - canvas.drawLine(Offset(x, gapBottom), Offset(x, lineEndY), paint); - } + if (dashed) { + paintVerticalDashedLine( + canvas, + x, + lineStartY, + lineEndY, + color, + strokeWidth, + dashWidth: dashWidth, + dashSpace: dashSpace, + ); } else { - // Draw full line without gap - if (dashed) { - paintVerticalDashedLine( - canvas, - x, - lineStartY, - lineEndY, - color, - strokeWidth, - dashWidth: dashWidth, - dashSpace: dashSpace, - ); - } else { - final Paint paint = Paint() - ..color = color - ..strokeWidth = strokeWidth; - canvas.drawLine(Offset(x, lineStartY), Offset(x, lineEndY), paint); - } + final Paint paint = Paint() + ..color = color + ..strokeWidth = strokeWidth; + canvas.drawLine(Offset(x, lineStartY), Offset(x, lineEndY), paint); } } - /// Paints a vertical line with text label centered in a gap at the anchor level. - /// - /// The [canvas] is the canvas on which to paint. - /// The [size] is the size of the drawing area. - /// The [text] is the text to display in the gap. - /// The [anchor] is the position where the gap should start (anchor level). - /// The [color] is the color for both the line and text. - /// The [zoom] is the zoom factor for text sizing. - /// The [dashed] parameter determines whether the line should be dashed. - static void paintVerticalLineWithText( + /// Paints an [icon] centered at the bottom (a few pixels above) of the chart at [x]. + static void paintBottomIcon( Canvas canvas, Size size, - String text, - Offset anchor, + double x, + IconData icon, + double zoom, Color color, - double zoom, { - required bool dashed, - }) { - final TextPainter textPainter = TextPainter( + ) { + final double iconSize = 24 * zoom; + + final TextPainter iconPainter = TextPainter( text: TextSpan( - text: text, + text: String.fromCharCode(icon.codePoint), style: TextStyle( + fontFamily: icon.fontFamily, + fontSize: iconSize, + package: icon.fontPackage, color: color, - fontSize: 12 * zoom, - fontWeight: FontWeight.bold, ), ), textDirection: TextDirection.ltr, )..layout(); - // Add padding around text and center it vertically within the gap - final double verticalPadding = 4 * zoom; - final double gapHeight = textPainter.height + (verticalPadding * 2); - - // Center text within the gap - final double textY = anchor.dy + (gapHeight - textPainter.height) / 2; - final double textX = anchor.dx - textPainter.width / 2; - - // Draw vertical line with gap starting at barrier level - paintVerticalTimeLine( + paintWithTextPainter( canvas, - size, - anchor.dx, - color: color, - dashed: dashed, - gapHeight: gapHeight, - gapOffset: anchor.dy, + painter: iconPainter, + anchor: Offset(x, size.height), + anchorAlignment: Alignment.bottomCenter, ); - - // Paint the text in the gap - textPainter.paint(canvas, Offset(textX, textY)); } - /// Paints an [icon] centered at the bottom (a few pixels above) of the chart at [x]. - static void paintBottomIcon( + /// Paints [text] centered at the bottom (a few pixels above) of the chart at [x]. + /// + /// This is similar to [paintBottomIcon] but for text labels (e.g., "1", "2"). + /// Used for checkpoint markers and exit time markers. + static void paintBottomText( Canvas canvas, Size size, double x, - IconData icon, + String text, double zoom, Color color, ) { - final double iconSize = 24 * zoom; + // Use a circular container size matching the icon size for consistent alignment + final double containerSize = 24 * zoom; - final TextPainter iconPainter = TextPainter( + final TextPainter textPainter = TextPainter( text: TextSpan( - text: String.fromCharCode(icon.codePoint), + text: text, style: TextStyle( - fontFamily: icon.fontFamily, - fontSize: iconSize, - package: icon.fontPackage, color: color, + fontSize: 14 * zoom, + fontWeight: FontWeight.w400, ), ), textDirection: TextDirection.ltr, )..layout(); - paintWithTextPainter( - canvas, - painter: iconPainter, - anchor: Offset(x, size.height), - anchorAlignment: Alignment.bottomCenter, + // Center the text within the container area at the bottom + final Offset textOffset = Offset( + x - textPainter.width / 2, + size.height - containerSize + (containerSize - textPainter.height) / 2, ); + + textPainter.paint(canvas, textOffset); } } From 70be9d645ef25ac340761649c7f7c13f8794c4e1 Mon Sep 17 00:00:00 2001 From: behnam-deriv <133759298+behnam-deriv@users.noreply.github.com> Date: Wed, 11 Feb 2026 15:08:07 +0800 Subject: [PATCH 3/7] chore: update example app with checkpoint markers --- example/lib/main.dart | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index d71ddd993..b23817bcc 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -120,10 +120,10 @@ class _FullscreenChartState extends State { late PrefServiceCache _prefService; - TradeType _currentTradeType = TradeType.multipliers; + TradeType _currentTradeType = TradeType.riseFall; // Dynamic marker duration in milliseconds - int _markerDurationMs = 1000 * 60 * 1 * 1; + int _markerDurationMs = 1000 * 5 * 1 * 1; // PnL label lifetime after marker end in milliseconds static const int _pnlLabelLifetimeMs = 4000; @@ -146,7 +146,7 @@ class _FullscreenChartState extends State { await _prefService.setDefaultValues({ 'appID': defaultAppID, 'endpoint': defaultEndpoint, - 'tradeType': TradeType.multipliers.value, + 'tradeType': TradeType.riseFall.value, }); // Load current trade type from preferences @@ -885,6 +885,19 @@ class _FullscreenChartState extends State { direction: marker.direction, markerType: MarkerType.entrySpot, ), + ChartMarker( + epoch: (endEpoch - marker.epoch) ~/ 2 + marker.epoch, + quote: marker.quote, + direction: marker.direction, + text: '1', + markerType: MarkerType.checkpointLine, + ), + ChartMarker( + epoch: (endEpoch - marker.epoch) ~/ 2 + marker.epoch, + quote: marker.quote, + direction: marker.direction, + markerType: MarkerType.checkpointLineCollapsed, + ), ChartMarker( epoch: endEpoch, quote: marker.quote, @@ -895,6 +908,7 @@ class _FullscreenChartState extends State { epoch: endEpoch, quote: marker.quote, direction: marker.direction, + text: '2', markerType: MarkerType.exitTime, ), ChartMarker( From 1bbd1fe9b9084dff4fa86dee0f7a24b6e8b6a023 Mon Sep 17 00:00:00 2001 From: behnam-deriv <133759298+behnam-deriv@users.noreply.github.com> Date: Wed, 11 Feb 2026 15:35:58 +0800 Subject: [PATCH 4/7] chore: update docs --- .../chart/data_visualization/markers/chart_marker.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart index 9d74261a4..8db654e74 100644 --- a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart +++ b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart @@ -175,7 +175,7 @@ class ChartMarker extends Marker { /// The [markerType] determines the type of marker, which determines its role and rendering. /// The [text] is the text to display on or near the marker. /// The [color] is the color of the marker. - /// The [hasReducedOpacity] determines whether the marker should be rendered with reduced (0.5) opacity. + /// The [hasReducedOpacity] determines whether the marker should be rendered with reduced opacity by 50%. ChartMarker({ required int epoch, required double quote, @@ -214,7 +214,7 @@ class ChartMarker extends Marker { /// If null, uses [style.upColor] for [MarkerDirection.up] or [style.downColor] for [MarkerDirection.down]. final Color? color; - /// Whether vertical line markers should be rendered with reduced (0.5) opacity. + /// Whether vertical line markers should be rendered with reduced opacity by 50%. /// /// When set to true, marker will be rendered at half opacity. This is useful for indicating markers that represent /// future or unreached checkpoints in multi-stage contracts. From 2033822ccd103994bfdad8eaec9f26e36d9ee3d7 Mon Sep 17 00:00:00 2001 From: behnam-deriv <133759298+behnam-deriv@users.noreply.github.com> Date: Wed, 11 Feb 2026 17:01:18 +0800 Subject: [PATCH 5/7] refactor: use paintWithTextPainter for painting bottom text --- .../helpers/paint_functions/paint_start_line.dart | 2 +- .../paint_functions/paint_time_marker_utils.dart | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart index a560d9314..d41220592 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_start_line.dart @@ -23,7 +23,7 @@ import 'package:flutter/material.dart'; /// /// The [canvas] is the canvas on which to paint the line and icon. /// The [size] is the size of the drawing area, used to determine the vertical extent of the line. -/// The [marker] is the chart marker (kept for signature parity with other line painters). +/// The [marker] is the chart marker used to determine line color. /// The [anchor] is the position on the canvas where the line should be anchored. /// The [style] is the marker style, which provides colors and icon styling information. /// The [theme] is the chart theme, which provides color schemes and styling. diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart index b293da25e..70711bbbf 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_time_marker_utils.dart @@ -89,9 +89,6 @@ class TimeMarkerPainters { double zoom, Color color, ) { - // Use a circular container size matching the icon size for consistent alignment - final double containerSize = 24 * zoom; - final TextPainter textPainter = TextPainter( text: TextSpan( text: text, @@ -104,12 +101,10 @@ class TimeMarkerPainters { textDirection: TextDirection.ltr, )..layout(); - // Center the text within the container area at the bottom - final Offset textOffset = Offset( - x - textPainter.width / 2, - size.height - containerSize + (containerSize - textPainter.height) / 2, + paintWithTextPainter( + canvas, + painter: textPainter, + anchor: Offset(x, size.height - 24 * zoom / 2), ); - - textPainter.paint(canvas, textOffset); } } From 241a359df61ec71f6f17388a1b7066ffd9c102ba Mon Sep 17 00:00:00 2001 From: behnam-deriv <133759298+behnam-deriv@users.noreply.github.com> Date: Wed, 11 Feb 2026 17:06:57 +0800 Subject: [PATCH 6/7] chore: update document --- .../chart/data_visualization/markers/chart_marker.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart index 8db654e74..dcfddc4b2 100644 --- a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart +++ b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart @@ -214,7 +214,7 @@ class ChartMarker extends Marker { /// If null, uses [style.upColor] for [MarkerDirection.up] or [style.downColor] for [MarkerDirection.down]. final Color? color; - /// Whether vertical line markers should be rendered with reduced opacity by 50%. + /// Whether marker should be rendered with reduced opacity by 50%. /// /// When set to true, marker will be rendered at half opacity. This is useful for indicating markers that represent /// future or unreached checkpoints in multi-stage contracts. From 56c183c70a9fdbfccf73a549deba18c8b0b53a11 Mon Sep 17 00:00:00 2001 From: behnam-deriv <133759298+behnam-deriv@users.noreply.github.com> Date: Thu, 12 Feb 2026 17:31:03 +0800 Subject: [PATCH 7/7] chore: update docs --- .../markers/chart_marker.dart | 8 +++---- .../paint_functions/paint_end_line.dart | 23 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart index dcfddc4b2..2038133e5 100644 --- a/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart +++ b/lib/src/deriv_chart/chart/data_visualization/markers/chart_marker.dart @@ -123,10 +123,10 @@ enum MarkerType { /// Represents a checkpoint line marker for multi-stage contracts. /// - /// This marker renders as a vertical dashed line similar to start/end time markers, - /// but without a bottom icon. It can display optional text (e.g., "1", "2") on the - /// line to indicate checkpoint sequence. Used for intermediate evaluation - /// points in contracts like Double Rise/Fall where multiple checkpoints need to be visualized. + /// This marker renders as a vertical dashed line similar to start/end time markers. + /// It can display optional text (e.g., "1", "2") at the bottom of the line to indicate + /// checkpoint sequence. Used for intermediate evaluation points in contracts like + /// Double Rise/Fall where multiple checkpoints need to be visualized. checkpointLine, /// Represents a compact solid checkpoint vertical line. diff --git a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart index b29967d91..1fbd93e49 100644 --- a/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart +++ b/lib/src/deriv_chart/chart/helpers/paint_functions/paint_end_line.dart @@ -6,28 +6,29 @@ import 'package:deriv_chart/src/theme/chart_theme.dart'; import 'package:deriv_chart/src/theme/painting_styles/marker_style.dart'; import 'package:flutter/material.dart'; -/// Renders a vertical dashed line with a flag icon to indicate the end time of a contract. +/// Renders a vertical dashed line with a flag icon or text at the bottom to indicate the end time of a contract. /// /// This function draws a vertical dashed line at the specified horizontal position, /// extending from near the top of the chart to near the bottom. The line visually -/// marks the end time of a contract or trade on a financial chart. It also renders -/// a flag icon near the bottom of the line or displays text if provided in the marker. +/// marks the end time of a contract or trade on a financial chart. If the marker has +/// text, it renders the text at the bottom; otherwise, it renders a flag icon. /// /// The function performs two main rendering operations: -/// 1. Draws a vertical dashed line using the `paintVerticalDashedLine` helper function -/// 2. Renders a flag icon near the bottom of the chart or text if provided in the marker +/// 1. Draws a vertical dashed line using the `paintVerticalTimeLine` helper function +/// 2. Renders either text or a flag icon at the bottom of the chart (conditionally) /// -/// The vertical line uses the background color from the provided style, and the icon -/// is styled according to the marker style with appropriate scaling based on the zoom factor. +/// The vertical line uses the color determined by the marker's direction or explicit color, +/// and the icon/text is styled according to the marker style with appropriate scaling based +/// on the zoom factor. /// -/// The [canvas] is the canvas on which to paint the line and icon. +/// The [canvas] is the canvas on which to paint the line and icon/text. /// The [size] is the size of the drawing area, used to determine the vertical extent of the line. -/// The [marker] is the chart marker (kept for signature parity with start line painter). +/// The [marker] is the chart marker used to determine line color and optional text. /// The [anchor] is the position on the canvas where the line should be anchored. /// The [style] is the marker style, which provides colors and icon styling information. /// The [theme] is the chart theme, which provides color schemes and styling. -/// The [zoom] is the zoom factor to apply to icon size and other dimensions. -/// The [opacity] is the opacity to apply to the line and icon. +/// The [zoom] is the zoom factor to apply to icon/text size and other dimensions. +/// The [opacity] is the opacity to apply to the line and icon/text. /// The [props] contains additional marker properties that can affect rendering. void paintEndLine( Canvas canvas,