Skip to content

Commit aa88388

Browse files
Fix ScatterChart and RadarChart to refresh when individual data points updated (#5785)
* Set notifyParent flag for chart controls Added notifyParent = true to relevant controls in scatter and radar chart implementations to ensure parent widgets are notified of changes in child controls. This improves reactivity and data propagation within chart components. * Pass TapDownDetails to tap event handlers Tap, secondary tap, and double tap event handlers now receive the last TapDownDetails as event data. This enables more detailed event information to be available for these gesture events. Fix #5784 * Add tertiary tap and long press event support Introduces handling for tertiary tap down, tap up, long press start, and long press end events in both Dart and Python GestureDetector controls. This enables detection and response to gestures performed with a tertiary button, expanding the range of supported pointer interactions.
1 parent 6b84074 commit aa88388

File tree

4 files changed

+100
-21
lines changed

4 files changed

+100
-21
lines changed

packages/flet/lib/src/controls/gesture_detector.dart

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class _GestureDetectorControlState extends State<GestureDetectorControl> {
3939
bool _rightPanActive = false;
4040
int _rightPanTimestamp = DateTime.now().millisecondsSinceEpoch;
4141
Offset _rightPanStart = Offset.zero;
42+
TapDownDetails? _lastTapDownDetails;
43+
TapDownDetails? _lastSecondaryTapDownDetails;
44+
TapDownDetails? _lastDoubleTapDownDetails;
4245

4346
@override
4447
void initState() {
@@ -68,13 +71,21 @@ class _GestureDetectorControlState extends State<GestureDetectorControl> {
6871
widget.control.getBool("on_secondary_tap_down", false)!;
6972
var onSecondaryTapUp =
7073
widget.control.getBool("on_secondary_tap_up", false)!;
74+
var onTertiaryTapDown =
75+
widget.control.getBool("on_tertiary_tap_down", false)!;
76+
var onTertiaryTapUp =
77+
widget.control.getBool("on_tertiary_tap_up", false)!;
7178
var onLongPressStart =
7279
widget.control.getBool("on_long_press_start", false)!;
7380
var onLongPressEnd = widget.control.getBool("on_long_press_end", false)!;
7481
var onSecondaryLongPressStart =
7582
widget.control.getBool("on_secondary_long_press_start", false)!;
7683
var onSecondaryLongPressEnd =
7784
widget.control.getBool("on_secondary_long_press_end", false)!;
85+
var onTertiaryLongPressStart =
86+
widget.control.getBool("on_tertiary_long_press_start", false)!;
87+
var onTertiaryLongPressEnd =
88+
widget.control.getBool("on_tertiary_long_press_end", false)!;
7889
var onDoubleTap = widget.control.getBool("on_double_tap", false)!;
7990
var onDoubleTapDown = widget.control.getBool("on_double_tap_down", false)!;
8091
var onHorizontalDragStart =
@@ -185,10 +196,14 @@ class _GestureDetectorControlState extends State<GestureDetectorControl> {
185196
onSecondaryTap |
186197
onSecondaryTapDown |
187198
onSecondaryTapUp |
199+
onTertiaryTapDown |
200+
onTertiaryTapUp |
188201
onLongPressStart |
189202
onLongPressEnd |
190203
onSecondaryLongPressStart |
191204
onSecondaryLongPressEnd |
205+
onTertiaryLongPressStart |
206+
onTertiaryLongPressEnd |
192207
onDoubleTap |
193208
onDoubleTapDown |
194209
onHorizontalDragStart |
@@ -217,30 +232,48 @@ class _GestureDetectorControlState extends State<GestureDetectorControl> {
217232
.nonNulls
218233
.toSet();
219234
}(),
220-
onTap: onTap ? () => widget.control.triggerEvent("tap") : null,
221-
onTapDown: onTapDown
222-
? (TapDownDetails details) {
223-
widget.control.triggerEvent("tap_down", details.toMap());
224-
}
235+
onTap: onTap
236+
? () => widget.control
237+
.triggerEvent("tap", _lastTapDownDetails?.toMap())
225238
: null,
239+
onTapDown: (TapDownDetails details) {
240+
if (onTapDown) {
241+
widget.control.triggerEvent("tap_down", details.toMap());
242+
}
243+
_lastTapDownDetails = details;
244+
},
226245
onTapUp: onTapUp
227246
? (TapUpDetails details) {
228247
widget.control.triggerEvent("tap_up", details.toMap());
229248
}
230249
: null,
231250
onSecondaryTap: onSecondaryTap
232-
? () => widget.control.triggerEvent("secondary_tap")
251+
? () => widget.control.triggerEvent(
252+
"secondary_tap", _lastSecondaryTapDownDetails?.toMap())
233253
: null,
234-
onSecondaryTapDown: onSecondaryTapDown
235-
? (TapDownDetails details) {
254+
onSecondaryTapDown: (TapDownDetails details) {
255+
if (onSecondaryTapDown) {
256+
widget.control
257+
.triggerEvent("secondary_tap_down", details.toMap());
258+
}
259+
_lastSecondaryTapDownDetails = details;
260+
},
261+
onSecondaryTapUp: onSecondaryTapUp
262+
? (TapUpDetails details) {
236263
widget.control
237-
.triggerEvent("secondary_tap_down", details.toMap());
264+
.triggerEvent("secondary_tap_up", details.toMap());
238265
}
239266
: null,
240-
onSecondaryTapUp: onSecondaryTapUp
267+
onTertiaryTapDown: (TapDownDetails details) {
268+
if (onTertiaryTapDown) {
269+
widget.control
270+
.triggerEvent("tertiary_tap_down", details.toMap());
271+
}
272+
},
273+
onTertiaryTapUp: onTertiaryTapUp
241274
? (TapUpDetails details) {
242275
widget.control
243-
.triggerEvent("secondary_tap_up", details.toMap());
276+
.triggerEvent("tertiary_tap_up", details.toMap());
244277
}
245278
: null,
246279
onLongPressStart: onLongPressStart
@@ -267,15 +300,28 @@ class _GestureDetectorControlState extends State<GestureDetectorControl> {
267300
"secondary_long_press_end", details.toMap());
268301
}
269302
: null,
270-
onDoubleTap: onDoubleTap
271-
? () => widget.control.triggerEvent("double_tap")
303+
onTertiaryLongPressStart: onTertiaryLongPressStart
304+
? (LongPressStartDetails details) {
305+
widget.control.triggerEvent(
306+
"tertiary_long_press_start", details.toMap());
307+
}
272308
: null,
273-
onDoubleTapDown: onDoubleTapDown
274-
? (TapDownDetails details) {
275-
widget.control
276-
.triggerEvent("double_tap_down", details.toMap());
309+
onTertiaryLongPressEnd: onTertiaryLongPressEnd
310+
? (LongPressEndDetails details) {
311+
widget.control.triggerEvent(
312+
"tertiary_long_press_end", details.toMap());
277313
}
278314
: null,
315+
onDoubleTap: onDoubleTap
316+
? () => widget.control.triggerEvent(
317+
"double_tap", _lastDoubleTapDownDetails?.toMap())
318+
: null,
319+
onDoubleTapDown: (TapDownDetails details) {
320+
if (onDoubleTapDown) {
321+
widget.control.triggerEvent("double_tap_down", details.toMap());
322+
}
323+
_lastDoubleTapDownDetails = details;
324+
},
279325
onHorizontalDragStart:
280326
(onHorizontalDragStart || onHorizontalDragUpdate)
281327
? handleHorizontalDragStart

sdk/python/packages/flet-charts/src/flutter/flet_charts/lib/src/scatter_chart.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class _ScatterChartControlState extends State<ScatterChartControl> {
3838
// Build list of ScatterSpotData
3939
final spotsAsControls = widget.control.children('spots');
4040
final spots = spotsAsControls.map((spot) {
41+
spot.notifyParent = true;
4142
var x = spot.getDouble('x', 0)!;
4243
var y = spot.getDouble('y', 0)!;
4344
return ScatterSpot(x, y,

sdk/python/packages/flet-charts/src/flutter/flet_charts/lib/src/utils/radar_chart.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,17 @@ class RadarChartEventData extends Equatable {
5151

5252
RadarDataSet parseRadarDataSet(
5353
Control dataSet, ThemeData theme, BuildContext context) {
54+
dataSet.notifyParent = true;
5455
final fillColor = dataSet.getColor("fill_color", context, Colors.cyan)!;
5556
final fillGradient = dataSet.getGradient("fill_gradient", theme);
5657
final borderColor = dataSet.getColor("border_color", context, Colors.cyan)!;
5758
final borderWidth = dataSet.getDouble("border_width", 2.0)!;
5859
final entryRadius = dataSet.getDouble("entry_radius", 5.0)!;
5960

60-
final entries = dataSet
61-
.children("entries")
62-
.map((entry) => RadarEntry(value: entry.getDouble("value", 0)!))
63-
.toList();
61+
final entries = dataSet.children("entries").map((entry) {
62+
entry.notifyParent = true;
63+
return RadarEntry(value: entry.getDouble("value", 0)!);
64+
}).toList();
6465

6566
return RadarDataSet(
6667
dataEntries: entries,
@@ -74,6 +75,7 @@ RadarDataSet parseRadarDataSet(
7475

7576
RadarChartTitle parseRadarChartTitle(
7677
Control title, ThemeData theme, double defaultAngle) {
78+
title.notifyParent = true;
7779
final spansValue = title.get("text_spans");
7880
final spans = spansValue != null
7981
? parseTextSpans(spansValue, theme, (control, eventName, [eventData]) {

sdk/python/packages/flet/src/flet/controls/core/gesture_detector.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ class GestureDetector(LayoutControl, AdaptiveControl):
128128
contacting the screen at a particular location.
129129
"""
130130

131+
on_tertiary_tap_down: Optional[EventHandler[TapEvent["GestureDetector"]]] = None
132+
"""
133+
Called when a pointer that might cause a tap with a tertiary button has contacted
134+
the screen at a particular location.
135+
"""
136+
137+
on_tertiary_tap_up: Optional[EventHandler[TapEvent["GestureDetector"]]] = None
138+
"""
139+
Called when a pointer that will trigger a tap with a tertiary button has stopped
140+
contacting the screen at a particular location.
141+
"""
142+
131143
on_long_press_start: Optional[
132144
EventHandler[LongPressStartEvent["GestureDetector"]]
133145
] = None
@@ -164,6 +176,24 @@ class GestureDetector(LayoutControl, AdaptiveControl):
164176
stopped contacting the screen.
165177
"""
166178

179+
on_tertiary_long_press_start: Optional[
180+
EventHandler[LongPressStartEvent["GestureDetector"]]
181+
] = None
182+
"""
183+
Called when a long press gesture with a tertiary button has been recognized.
184+
185+
Triggered when a pointer has remained in contact with the screen at the same
186+
location for a long period of time.
187+
"""
188+
189+
on_tertiary_long_press_end: Optional[
190+
EventHandler[LongPressEndEvent["GestureDetector"]]
191+
] = None
192+
"""
193+
Called when a pointer that has triggered a long-press with a tertiary button has
194+
stopped contacting the screen.
195+
"""
196+
167197
on_double_tap: Optional[EventHandler[TapEvent["GestureDetector"]]] = None
168198
"""
169199
The user has tapped the screen with a primary button at the same location twice

0 commit comments

Comments
 (0)