@@ -14,28 +14,16 @@ class InteractiveFlagsPage extends StatefulWidget {
1414}
1515
1616class _InteractiveFlagsPageState extends State <InteractiveFlagsPage > {
17- static const availableFlags = {
18- 'Movement' : {
19- InteractiveFlag .drag: 'Drag' ,
20- InteractiveFlag .flingAnimation: 'Fling' ,
21- InteractiveFlag .pinchMove: 'Pinch' ,
22- },
23- 'Zooming' : {
24- InteractiveFlag .pinchZoom: 'Pinch' ,
25- InteractiveFlag .scrollWheelZoom: 'Scroll' ,
26- InteractiveFlag .doubleTapZoom: 'Double tap' ,
27- InteractiveFlag .doubleTapDragZoom: '+ drag' ,
28- },
29- 'Rotation' : {
30- InteractiveFlag .rotate: 'Twist' ,
31- },
32- };
17+ final flagsSet =
18+ ValueNotifier (InteractiveFlag .drag | InteractiveFlag .pinchZoom);
3319
34- int flags = InteractiveFlag .drag | InteractiveFlag .pinchZoom;
3520 bool keyboardCursorRotate = false ;
21+ bool keyboardArrowsMove = false ;
22+ bool keyboardWASDMove = false ;
23+ bool keyboardQERotate = false ;
24+ bool keyboardRFZoom = false ;
3625
3726 MapEvent ? _latestEvent;
38-
3927 @override
4028 Widget build (BuildContext context) {
4129 final screenWidth = MediaQuery .sizeOf (context).width;
@@ -50,58 +38,181 @@ class _InteractiveFlagsPageState extends State<InteractiveFlagsPage> {
5038 direction: screenWidth >= 600 ? Axis .horizontal : Axis .vertical,
5139 mainAxisSize: MainAxisSize .max,
5240 mainAxisAlignment: MainAxisAlignment .spaceEvenly,
53- children: availableFlags.entries
54- .map <Widget ?>(
55- (category) => Column (
41+ children: [
42+ Column (
43+ children: [
44+ const Text (
45+ 'Move/Pan' ,
46+ style: TextStyle (
47+ fontWeight: FontWeight .bold,
48+ ),
49+ ),
50+ const SizedBox (height: 6 ),
51+ Row (
52+ mainAxisSize: MainAxisSize .min,
53+ crossAxisAlignment: CrossAxisAlignment .start,
5654 children: [
57- Text (
58- category.key,
59- style: const TextStyle (fontWeight: FontWeight .bold),
55+ InteractiveFlagCheckbox (
56+ name: 'Drag' ,
57+ flag: InteractiveFlag .drag,
58+ flagsSet: flagsSet,
59+ ),
60+ const SizedBox (width: 8 ),
61+ InteractiveFlagCheckbox (
62+ name: 'Fling' ,
63+ flag: InteractiveFlag .flingAnimation,
64+ flagsSet: flagsSet,
6065 ),
61- Row (
62- mainAxisSize: MainAxisSize .min,
63- children: < Widget > [
64- ...category.value.entries.map (
65- (e) => Column (
66- children: [
67- Checkbox .adaptive (
68- value:
69- InteractiveFlag .hasFlag (e.key, flags),
70- onChanged: (enabled) {
71- if (! enabled! ) {
72- setState (() => flags & = ~ e.key);
73- return ;
74- }
75- setState (() => flags | = e.key);
76- },
77- ),
78- Text (e.value),
79- ],
66+ const SizedBox (width: 8 ),
67+ InteractiveFlagCheckbox (
68+ name: 'Pinch' ,
69+ flag: InteractiveFlag .pinchMove,
70+ flagsSet: flagsSet,
71+ ),
72+ const SizedBox (width: 8 ),
73+ Column (
74+ children: [
75+ Checkbox .adaptive (
76+ value: keyboardArrowsMove,
77+ onChanged: (enabled) => setState (
78+ () => keyboardArrowsMove = enabled! ,
8079 ),
8180 ),
82- if (category.key == 'Rotation' ) ...[
83- Column (
84- children: [
85- Checkbox .adaptive (
86- value: keyboardCursorRotate,
87- onChanged: (enabled) => setState (
88- () => keyboardCursorRotate = enabled! ),
89- ),
90- const Text ('Cursor & CTRL' ),
91- ],
81+ const Text (
82+ 'Keyboard\n Arrows' ,
83+ textAlign: TextAlign .center,
84+ ),
85+ ],
86+ ),
87+ const SizedBox (width: 8 ),
88+ Column (
89+ children: [
90+ Checkbox .adaptive (
91+ value: keyboardWASDMove,
92+ onChanged: (enabled) => setState (
93+ () => keyboardWASDMove = enabled! ,
9294 ),
93- ]
94- ].interleave (const SizedBox (width: 12 )).toList ()
95- ..removeLast (),
96- )
95+ ),
96+ const Text (
97+ 'Keyboard\n W/A/S/D' ,
98+ textAlign: TextAlign .center,
99+ ),
100+ ],
101+ ),
97102 ],
103+ )
104+ ],
105+ ),
106+ const SizedBox (width: 12 ),
107+ Column (
108+ children: [
109+ const Text (
110+ 'Zoom' ,
111+ style: TextStyle (
112+ fontWeight: FontWeight .bold,
113+ ),
98114 ),
99- )
100- .interleave (
101- screenWidth >= 600 ? null : const SizedBox (height: 12 ),
102- )
103- .whereType <Widget >()
104- .toList (),
115+ const SizedBox (height: 6 ),
116+ Row (
117+ mainAxisSize: MainAxisSize .min,
118+ crossAxisAlignment: CrossAxisAlignment .start,
119+ children: [
120+ InteractiveFlagCheckbox (
121+ name: 'Pinch' ,
122+ flag: InteractiveFlag .pinchZoom,
123+ flagsSet: flagsSet,
124+ ),
125+ const SizedBox (width: 8 ),
126+ InteractiveFlagCheckbox (
127+ name: 'Scroll' ,
128+ flag: InteractiveFlag .scrollWheelZoom,
129+ flagsSet: flagsSet,
130+ ),
131+ const SizedBox (width: 8 ),
132+ InteractiveFlagCheckbox (
133+ name: 'Double tap' ,
134+ flag: InteractiveFlag .doubleTapZoom,
135+ flagsSet: flagsSet,
136+ ),
137+ const SizedBox (width: 8 ),
138+ InteractiveFlagCheckbox (
139+ name: '+ drag' ,
140+ flag: InteractiveFlag .doubleTapDragZoom,
141+ flagsSet: flagsSet,
142+ ),
143+ const SizedBox (width: 8 ),
144+ Column (
145+ children: [
146+ Checkbox .adaptive (
147+ value: keyboardRFZoom,
148+ onChanged: (enabled) => setState (
149+ () => keyboardRFZoom = enabled! ,
150+ ),
151+ ),
152+ const Text (
153+ 'Keyboard\n R/F' ,
154+ textAlign: TextAlign .center,
155+ ),
156+ ],
157+ ),
158+ ],
159+ )
160+ ],
161+ ),
162+ const SizedBox (width: 12 ),
163+ Column (
164+ children: [
165+ const Text (
166+ 'Rotate' ,
167+ style: TextStyle (
168+ fontWeight: FontWeight .bold,
169+ ),
170+ ),
171+ const SizedBox (height: 6 ),
172+ Row (
173+ mainAxisSize: MainAxisSize .min,
174+ crossAxisAlignment: CrossAxisAlignment .start,
175+ children: [
176+ InteractiveFlagCheckbox (
177+ name: 'Twist' ,
178+ flag: InteractiveFlag .rotate,
179+ flagsSet: flagsSet,
180+ ),
181+ const SizedBox (width: 8 ),
182+ Column (
183+ children: [
184+ Checkbox .adaptive (
185+ value: keyboardCursorRotate,
186+ onChanged: (enabled) => setState (
187+ () => keyboardCursorRotate = enabled! ,
188+ ),
189+ ),
190+ const Text (
191+ 'Cursor\n & CTRL' ,
192+ textAlign: TextAlign .center,
193+ ),
194+ ],
195+ ),
196+ const SizedBox (width: 8 ),
197+ Column (
198+ children: [
199+ Checkbox .adaptive (
200+ value: keyboardQERotate,
201+ onChanged: (enabled) => setState (
202+ () => keyboardQERotate = enabled! ,
203+ ),
204+ ),
205+ const Text (
206+ 'Keyboard\n Q/E' ,
207+ textAlign: TextAlign .center,
208+ ),
209+ ],
210+ ),
211+ ],
212+ )
213+ ],
214+ ),
215+ ],
105216 ),
106217 const Divider (),
107218 Padding (
@@ -115,23 +226,33 @@ class _InteractiveFlagsPageState extends State<InteractiveFlagsPage> {
115226 ),
116227 ),
117228 Expanded (
118- child: FlutterMap (
119- options: MapOptions (
120- onMapEvent: (evt) => setState (() => _latestEvent = evt),
121- initialCenter: const LatLng (51.5 , - 0.09 ),
122- initialZoom: 11 ,
123- interactionOptions: InteractionOptions (
124- flags: flags,
125- cursorKeyboardRotationOptions:
126- CursorKeyboardRotationOptions (
127- isKeyTrigger: (key) =>
128- keyboardCursorRotate &&
129- CursorKeyboardRotationOptions .defaultTriggerKeys
130- .contains (key),
229+ child: ValueListenableBuilder (
230+ valueListenable: flagsSet,
231+ builder: (context, value, child) => FlutterMap (
232+ options: MapOptions (
233+ onMapEvent: (evt) => setState (() => _latestEvent = evt),
234+ initialCenter: const LatLng (51.5 , - 0.09 ),
235+ initialZoom: 11 ,
236+ interactionOptions: InteractionOptions (
237+ flags: value,
238+ cursorKeyboardRotationOptions:
239+ CursorKeyboardRotationOptions (
240+ isKeyTrigger: (key) =>
241+ keyboardCursorRotate &&
242+ CursorKeyboardRotationOptions .defaultTriggerKeys
243+ .contains (key),
244+ ),
245+ keyboardOptions: KeyboardOptions (
246+ enableArrowKeysPanning: keyboardArrowsMove,
247+ enableWASDPanning: keyboardWASDMove,
248+ enableQERotating: keyboardQERotate,
249+ enableRFZooming: keyboardRFZoom,
250+ ),
131251 ),
132252 ),
253+ children: [child! ],
133254 ),
134- children : [ openStreetMapTileLayer] ,
255+ child : openStreetMapTileLayer,
135256 ),
136257 ),
137258 ],
@@ -186,11 +307,32 @@ class _InteractiveFlagsPageState extends State<InteractiveFlagsPage> {
186307 }
187308}
188309
189- extension _IterableExt <E > on Iterable <E > {
190- Iterable <E > interleave (E separator) sync * {
191- for (int i = 0 ; i < length; i++ ) {
192- yield elementAt (i);
193- if (i < length) yield separator;
194- }
310+ class InteractiveFlagCheckbox extends StatelessWidget {
311+ const InteractiveFlagCheckbox ({
312+ super .key,
313+ required this .name,
314+ required this .flag,
315+ required this .flagsSet,
316+ });
317+
318+ final String name;
319+ final int flag;
320+ final ValueNotifier <int > flagsSet;
321+
322+ @override
323+ Widget build (BuildContext context) {
324+ return Column (
325+ children: [
326+ ValueListenableBuilder (
327+ valueListenable: flagsSet,
328+ builder: (context, value, _) => Checkbox .adaptive (
329+ value: InteractiveFlag .hasFlag (flag, value),
330+ onChanged: (enabled) =>
331+ flagsSet.value = ! enabled! ? value & = ~ flag : value | = flag,
332+ ),
333+ ),
334+ Text (name),
335+ ],
336+ );
195337 }
196338}
0 commit comments