1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'package:flutter/material.dart'; |
6 | import 'package:flutter/rendering.dart'; |
7 | |
8 | /// Flutter code sample for [SelectionContainer]. |
9 | |
10 | void main() => runApp(const SelectionContainerExampleApp()); |
11 | |
12 | class SelectionContainerExampleApp extends StatelessWidget { |
13 | const SelectionContainerExampleApp({super.key}); |
14 | |
15 | @override |
16 | Widget build(BuildContext context) { |
17 | return MaterialApp( |
18 | home: SelectionArea( |
19 | child: Scaffold( |
20 | appBar: AppBar(title: const Text('SelectionContainer Sample' )), |
21 | body: const Center( |
22 | child: SelectionAllOrNoneContainer( |
23 | child: Column( |
24 | mainAxisAlignment: MainAxisAlignment.center, |
25 | children: <Widget>[Text('Row 1' ), Text('Row 2' ), Text('Row 3' )], |
26 | ), |
27 | ), |
28 | ), |
29 | ), |
30 | ), |
31 | ); |
32 | } |
33 | } |
34 | |
35 | class SelectionAllOrNoneContainer extends StatefulWidget { |
36 | const SelectionAllOrNoneContainer({super.key, required this.child}); |
37 | |
38 | final Widget child; |
39 | |
40 | @override |
41 | State<StatefulWidget> createState() => _SelectionAllOrNoneContainerState(); |
42 | } |
43 | |
44 | class _SelectionAllOrNoneContainerState extends State<SelectionAllOrNoneContainer> { |
45 | final SelectAllOrNoneContainerDelegate delegate = SelectAllOrNoneContainerDelegate(); |
46 | |
47 | @override |
48 | void dispose() { |
49 | delegate.dispose(); |
50 | super.dispose(); |
51 | } |
52 | |
53 | @override |
54 | Widget build(BuildContext context) { |
55 | return SelectionContainer(delegate: delegate, child: widget.child); |
56 | } |
57 | } |
58 | |
59 | class SelectAllOrNoneContainerDelegate extends MultiSelectableSelectionContainerDelegate { |
60 | Offset? _adjustedStartEdge; |
61 | Offset? _adjustedEndEdge; |
62 | bool _isSelected = false; |
63 | |
64 | // This method is called when newly added selectable is in the current |
65 | // selected range. |
66 | @override |
67 | void ensureChildUpdated(Selectable selectable) { |
68 | if (_isSelected) { |
69 | dispatchSelectionEventToChild(selectable, const SelectAllSelectionEvent()); |
70 | } |
71 | } |
72 | |
73 | @override |
74 | SelectionResult handleSelectWord(SelectWordSelectionEvent event) { |
75 | // Treat select word as select all. |
76 | return handleSelectAll(const SelectAllSelectionEvent()); |
77 | } |
78 | |
79 | @override |
80 | SelectionResult handleSelectionEdgeUpdate(SelectionEdgeUpdateEvent event) { |
81 | final Rect containerRect = Rect.fromLTWH(0, 0, containerSize.width, containerSize.height); |
82 | final Matrix4 globalToLocal = getTransformTo(null)..invert(); |
83 | final Offset localOffset = MatrixUtils.transformPoint(globalToLocal, event.globalPosition); |
84 | final Offset adjustOffset = SelectionUtils.adjustDragOffset(containerRect, localOffset); |
85 | if (event.type == SelectionEventType.startEdgeUpdate) { |
86 | _adjustedStartEdge = adjustOffset; |
87 | } else { |
88 | _adjustedEndEdge = adjustOffset; |
89 | } |
90 | // Select all content if the selection rect intercepts with the rect. |
91 | if (_adjustedStartEdge != null && _adjustedEndEdge != null) { |
92 | final Rect selectionRect = Rect.fromPoints(_adjustedStartEdge!, _adjustedEndEdge!); |
93 | if (!selectionRect.intersect(containerRect).isEmpty) { |
94 | handleSelectAll(const SelectAllSelectionEvent()); |
95 | } else { |
96 | super.handleClearSelection(const ClearSelectionEvent()); |
97 | } |
98 | } else { |
99 | super.handleClearSelection(const ClearSelectionEvent()); |
100 | } |
101 | return SelectionUtils.getResultBasedOnRect(containerRect, localOffset); |
102 | } |
103 | |
104 | @override |
105 | SelectionResult handleClearSelection(ClearSelectionEvent event) { |
106 | _adjustedStartEdge = null; |
107 | _adjustedEndEdge = null; |
108 | _isSelected = false; |
109 | return super.handleClearSelection(event); |
110 | } |
111 | |
112 | @override |
113 | SelectionResult handleSelectAll(SelectAllSelectionEvent event) { |
114 | _isSelected = true; |
115 | return super.handleSelectAll(event); |
116 | } |
117 | } |
118 | |