Skip to content

Commit 4040e48

Browse files
committed
[PR fluttercandies#27 feature] Repaint when the last candle changed
1 parent 4f942a5 commit 4040e48

File tree

5 files changed

+129
-1
lines changed

5 files changed

+129
-1
lines changed

lib/src/candle_data.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,29 @@ class CandleData {
7171
return result;
7272
}
7373

74+
@override
75+
bool operator ==(Object other) =>
76+
identical(this, other) ||
77+
other is CandleData &&
78+
runtimeType == other.runtimeType &&
79+
timestamp == other.timestamp &&
80+
open == other.open &&
81+
high == other.high &&
82+
low == other.low &&
83+
close == other.close &&
84+
volume == other.volume &&
85+
trends == other.trends;
86+
87+
@override
88+
int get hashCode =>
89+
timestamp.hashCode ^
90+
open.hashCode ^
91+
high.hashCode ^
92+
low.hashCode ^
93+
close.hashCode ^
94+
volume.hashCode ^
95+
trends.hashCode;
96+
7497
@override
7598
String toString() => "<CandleData ($timestamp: $close)>";
7699
}

lib/src/chart_painter.dart

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class ChartPainter extends CustomPainter {
2727
// Draw time labels (dates) & price labels
2828
_drawTimeLabels(canvas, params);
2929
_drawPriceGridAndLabels(canvas, params);
30+
_drawCurrentPriceLabel(canvas, params);
31+
_drawCurrentPriceLine(canvas, params);
3032

3133
// Draw prices, volumes & trend line
3234
canvas.save();
@@ -107,6 +109,65 @@ class ChartPainter extends CustomPainter {
107109
});
108110
}
109111

112+
void _drawCurrentPriceLabel(
113+
Canvas canvas,
114+
PainterParams params,
115+
) {
116+
final currentPrice = params.currentPrice;
117+
if (currentPrice == null) {
118+
return;
119+
}
120+
final priceTp = TextPainter(
121+
text: TextSpan(
122+
text: getPriceLabel(currentPrice),
123+
style: params.style.currentPriceStyle.labelStyle,
124+
),
125+
)
126+
..textDirection = TextDirection.ltr
127+
..layout();
128+
129+
final dx = params.chartWidth + 4;
130+
final dy =
131+
params.fitPrice(currentPrice).clamp(0, params.chartHeight).toDouble() -
132+
priceTp.height / 2;
133+
134+
final padding = params.style.currentPriceStyle.rectPadding;
135+
final radius = params.style.currentPriceStyle.rectRadius;
136+
final rectColor = params.style.currentPriceStyle.rectColor;
137+
138+
final rect = Rect.fromLTWH(
139+
dx, dy, priceTp.width + 2 * padding, priceTp.height + 2 * padding);
140+
final rrect = RRect.fromRectAndRadius(rect, Radius.circular(radius));
141+
canvas.drawRRect(rrect, Paint()..color = rectColor);
142+
143+
priceTp.paint(canvas, Offset(dx + padding, dy + padding));
144+
}
145+
146+
void _drawCurrentPriceLine(Canvas canvas, PainterParams params) {
147+
final currentPrice = params.currentPrice;
148+
if (currentPrice == null) {
149+
return;
150+
}
151+
final paint = Paint()
152+
..color = Colors.red
153+
..strokeWidth = 1
154+
..style = PaintingStyle.stroke;
155+
156+
final dashWidth = 4.0;
157+
final dashSpace = 2.0;
158+
double startX = 0;
159+
final clampedPrice =
160+
params.fitPrice(currentPrice).clamp(0, params.chartHeight).toDouble();
161+
while (startX < params.chartWidth) {
162+
canvas.drawLine(
163+
Offset(startX, clampedPrice),
164+
Offset(startX + dashWidth, clampedPrice),
165+
paint,
166+
);
167+
startX += dashWidth + dashSpace;
168+
}
169+
}
170+
110171
void _drawSingleDay(canvas, PainterParams params, int i) {
111172
final candle = params.candles[i];
112173
final x = i * params.candleWidth;

lib/src/chart_style.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class ChartStyle {
5454
/// This appears when user clicks on the chart.
5555
final Color overlayBackgroundColor;
5656

57+
/// The style of current price labels (on the right of the chart).
58+
final CurrentPriceStyle currentPriceStyle;
59+
5760
const ChartStyle({
5861
this.volumeHeightFactor = 0.2,
5962
this.priceLabelWidth = 48.0,
@@ -77,5 +80,34 @@ class ChartStyle {
7780
this.priceGridLineColor = Colors.grey,
7881
this.selectionHighlightColor = const Color(0x33757575),
7982
this.overlayBackgroundColor = const Color(0xEE757575),
83+
this.currentPriceStyle = const CurrentPriceStyle(
84+
labelStyle: TextStyle(
85+
fontSize: 12,
86+
color: Colors.white,
87+
),
88+
rectPadding: 4.0,
89+
rectRadius: 2.0,
90+
rectColor: Colors.red),
91+
});
92+
}
93+
94+
class CurrentPriceStyle {
95+
const CurrentPriceStyle({
96+
required this.labelStyle,
97+
required this.rectPadding,
98+
required this.rectRadius,
99+
required this.rectColor,
80100
});
101+
102+
/// The style of current price labels (on the right of the chart).
103+
final TextStyle labelStyle;
104+
105+
/// The padding around the current price rect.
106+
final double rectPadding;
107+
108+
/// The radius of the current price rect.
109+
final double rectRadius;
110+
111+
/// The color of the current price rect.
112+
final Color rectColor;
81113
}

lib/src/interactive_chart.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class InteractiveChart extends StatefulWidget {
6666
/// Provides X-axis offset details.
6767
final ValueChanged<XAxisOffsetDetails>? onXOffsetChanged;
6868

69+
/// The current price to be displayed on the right side of the chart.
70+
final double? currentPrice;
71+
6972
const InteractiveChart({
7073
Key? key,
7174
required this.candles,
@@ -76,6 +79,7 @@ class InteractiveChart extends StatefulWidget {
7679
this.overlayInfo,
7780
this.onTap,
7881
this.onCandleResize,
82+
this.currentPrice,
7983
this.onXOffsetChanged,
8084
}) : this.style = style ?? const ChartStyle(),
8185
assert(candles.length >= 3,
@@ -192,6 +196,7 @@ class _InteractiveChartState extends State<InteractiveChart> {
192196
tapPosition: _tapPosition,
193197
leadingTrends: leadingTrends,
194198
trailingTrends: trailingTrends,
199+
currentPrice: widget.currentPrice,
195200
),
196201
),
197202
duration: Duration(milliseconds: 300),

lib/src/painter_params.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import 'dart:ui';
2+
23
import 'package:flutter/widgets.dart';
34

4-
import 'chart_style.dart';
55
import 'candle_data.dart';
6+
import 'chart_style.dart';
67

78
class PainterParams {
89
final List<CandleData> candles;
10+
final double? currentPrice;
911
final ChartStyle style;
1012
final Size size;
1113
final double candleWidth;
@@ -23,6 +25,7 @@ class PainterParams {
2325

2426
PainterParams({
2527
required this.candles,
28+
this.currentPrice,
2629
required this.style,
2730
required this.size,
2831
required this.candleWidth,
@@ -97,12 +100,16 @@ class PainterParams {
97100
tapPosition: b.tapPosition,
98101
leadingTrends: b.leadingTrends,
99102
trailingTrends: b.trailingTrends,
103+
currentPrice:
104+
b.currentPrice != null ? lerpField((p) => p.currentPrice!) : null,
100105
);
101106
}
102107

103108
bool shouldRepaint(PainterParams other) {
104109
if (candles.length != other.candles.length) return true;
105110

111+
if (other.currentPrice != currentPrice) return true;
112+
106113
if (size != other.size ||
107114
candleWidth != other.candleWidth ||
108115
startOffset != other.startOffset ||

0 commit comments

Comments
 (0)