@@ -4,6 +4,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
4
4
import 'package:material_leap/material_leap.dart' ;
5
5
import 'package:phosphor_flutter/phosphor_flutter.dart' ;
6
6
import 'package:setonix/bloc/editor.dart' ;
7
+ import 'package:setonix/helpers/vector.dart' ;
7
8
import 'package:setonix_api/setonix_api.dart' ;
8
9
9
10
class DecksEditorPage extends StatelessWidget {
@@ -146,8 +147,126 @@ class _DeckEditorDialogState extends State<DeckEditorDialog> {
146
147
),
147
148
],
148
149
),
149
- SizedBox (),
150
- SizedBox (),
150
+ Stack (
151
+ children: [
152
+ ListView .builder (
153
+ itemCount: value.figures.length,
154
+ itemBuilder: (context, index) {
155
+ final figure = value.figures[index];
156
+ return ListTile (
157
+ title: Text (figure.name),
158
+ onTap: () async {
159
+ final bloc = context.read <EditorCubit >();
160
+ final result =
161
+ await showDialog <FigureDeckDefinition >(
162
+ context: context,
163
+ builder: (context) => BlocProvider .value (
164
+ value: bloc,
165
+ child: _DeckFigureEditorDialog (
166
+ value: figure,
167
+ ),
168
+ ),
169
+ );
170
+ if (result == null ) return ;
171
+ setState (() {
172
+ value.figures[index] = result;
173
+ });
174
+ },
175
+ trailing: IconButton (
176
+ icon: const Icon (PhosphorIconsLight .trash),
177
+ onPressed: () {
178
+ setState (() {
179
+ value.figures.removeAt (index);
180
+ });
181
+ },
182
+ ),
183
+ );
184
+ },
185
+ ),
186
+ Align (
187
+ alignment: Alignment .bottomCenter,
188
+ child: FloatingActionButton .extended (
189
+ onPressed: () async {
190
+ final bloc = context.read <EditorCubit >();
191
+ final result =
192
+ await showDialog <FigureDeckDefinition >(
193
+ context: context,
194
+ builder: (context) => BlocProvider .value (
195
+ value: bloc,
196
+ child: _DeckFigureEditorDialog (),
197
+ ),
198
+ );
199
+ if (result == null ) return ;
200
+ setState (() {
201
+ value.figures.add (result);
202
+ });
203
+ },
204
+ icon: const Icon (PhosphorIconsLight .plus),
205
+ label: Text (AppLocalizations .of (context).create),
206
+ ),
207
+ ),
208
+ ],
209
+ ),
210
+ Stack (
211
+ children: [
212
+ ListView .builder (
213
+ itemCount: value.boards.length,
214
+ itemBuilder: (context, index) {
215
+ final board = value.boards[index];
216
+ return ListTile (
217
+ title: Text (board.name),
218
+ onTap: () async {
219
+ final bloc = context.read <EditorCubit >();
220
+ final result =
221
+ await showDialog <BoardDeckDefinition >(
222
+ context: context,
223
+ builder: (context) => BlocProvider .value (
224
+ value: bloc,
225
+ child: _DeckBoardEditorDialog (
226
+ value: board,
227
+ ),
228
+ ),
229
+ );
230
+ if (result == null ) return ;
231
+ setState (() {
232
+ value.boards[index] = result;
233
+ });
234
+ },
235
+ trailing: IconButton (
236
+ icon: const Icon (PhosphorIconsLight .trash),
237
+ onPressed: () {
238
+ setState (() {
239
+ value.boards.removeAt (index);
240
+ });
241
+ },
242
+ ),
243
+ );
244
+ },
245
+ ),
246
+ Align (
247
+ alignment: Alignment .bottomCenter,
248
+ child: FloatingActionButton .extended (
249
+ onPressed: () async {
250
+ final bloc = context.read <EditorCubit >();
251
+ final result =
252
+ await showDialog <BoardDeckDefinition >(
253
+ context: context,
254
+ builder: (context) => BlocProvider .value (
255
+ value: bloc,
256
+ child: _DeckBoardEditorDialog (),
257
+ ),
258
+ );
259
+ if (result == null ) return ;
260
+ setState (() {
261
+ value.boards.add (result);
262
+ });
263
+ },
264
+ icon: const Icon (PhosphorIconsLight .plus),
265
+ label: Text (AppLocalizations .of (context).create),
266
+ ),
267
+ ),
268
+ ],
269
+ ),
151
270
],
152
271
),
153
272
),
@@ -172,3 +291,197 @@ class _DeckEditorDialogState extends State<DeckEditorDialog> {
172
291
);
173
292
}
174
293
}
294
+
295
+ class _DeckFigureEditorDialog extends StatefulWidget {
296
+ final FigureDeckDefinition ? value;
297
+
298
+ const _DeckFigureEditorDialog ({
299
+ this .value,
300
+ });
301
+
302
+ @override
303
+ State <_DeckFigureEditorDialog > createState () =>
304
+ __DeckFigureEditorDialogState ();
305
+ }
306
+
307
+ class __DeckFigureEditorDialogState extends State <_DeckFigureEditorDialog > {
308
+ FigureDeckDefinition ? _value;
309
+
310
+ @override
311
+ void initState () {
312
+ super .initState ();
313
+ _value = widget.value;
314
+ }
315
+
316
+ @override
317
+ Widget build (BuildContext context) {
318
+ return ResponsiveAlertDialog (
319
+ title: Text (AppLocalizations .of (context).figure),
320
+ constraints: const BoxConstraints (maxWidth: LeapBreakpoints .compact),
321
+ content: BlocBuilder <EditorCubit , SetonixData >(
322
+ builder: (context, state) {
323
+ final figure = _value == null ? null : state.getFigure (_value! .name);
324
+ return ListView (
325
+ shrinkWrap: true ,
326
+ children: [
327
+ DropdownMenu <String >(
328
+ dropdownMenuEntries: state.getFigures ().map ((e) {
329
+ return DropdownMenuEntry (
330
+ value: e,
331
+ label: e,
332
+ );
333
+ }).toList (),
334
+ label: Text (AppLocalizations .of (context).name),
335
+ initialSelection: _value? .name,
336
+ expandedInsets: EdgeInsets .all (8 ),
337
+ onSelected: (value) {
338
+ if (value == null ) return ;
339
+ setState (() {
340
+ _value = FigureDeckDefinition (name: value);
341
+ });
342
+ },
343
+ ),
344
+ if (figure != null ) ...[
345
+ const SizedBox (height: 8 ),
346
+ DropdownMenu <String >(
347
+ initialSelection: _value? .variation,
348
+ label: Text (AppLocalizations .of (context).variation),
349
+ expandedInsets: EdgeInsets .all (8 ),
350
+ dropdownMenuEntries: ['' , ...figure.variations.keys].map ((e) {
351
+ return DropdownMenuEntry (
352
+ value: e,
353
+ label:
354
+ e.isEmpty ? AppLocalizations .of (context).notSet : e,
355
+ );
356
+ }).toList (),
357
+ onSelected: (value) {
358
+ if (value == null ) return ;
359
+ setState (() {
360
+ _value = FigureDeckDefinition (
361
+ name: _value! .name,
362
+ variation: value,
363
+ );
364
+ });
365
+ },
366
+ ),
367
+ const SizedBox (height: 8 ),
368
+ OffsetListTile (
369
+ title: Text (AppLocalizations .of (context).position),
370
+ value: _value! .position.toOffset (),
371
+ onChanged: (value) {
372
+ setState (() {
373
+ _value = FigureDeckDefinition (
374
+ name: _value! .name,
375
+ variation: _value! .variation,
376
+ position: value.toDefinition (),
377
+ );
378
+ });
379
+ },
380
+ ),
381
+ ],
382
+ ],
383
+ );
384
+ },
385
+ ),
386
+ actions: [
387
+ TextButton (
388
+ onPressed: () {
389
+ Navigator .of (context).pop ();
390
+ },
391
+ child: Text (AppLocalizations .of (context).cancel),
392
+ ),
393
+ ElevatedButton (
394
+ onPressed: () {
395
+ Navigator .of (context).pop (_value);
396
+ },
397
+ child: Text (AppLocalizations .of (context).save),
398
+ ),
399
+ ],
400
+ );
401
+ }
402
+ }
403
+
404
+ class _DeckBoardEditorDialog extends StatefulWidget {
405
+ final BoardDeckDefinition ? value;
406
+
407
+ const _DeckBoardEditorDialog ({
408
+ this .value,
409
+ });
410
+
411
+ @override
412
+ State <_DeckBoardEditorDialog > createState () => __DeckBoardEditorDialogState ();
413
+ }
414
+
415
+ class __DeckBoardEditorDialogState extends State <_DeckBoardEditorDialog > {
416
+ BoardDeckDefinition ? _value;
417
+
418
+ @override
419
+ void initState () {
420
+ super .initState ();
421
+ _value = widget.value;
422
+ }
423
+
424
+ @override
425
+ Widget build (BuildContext context) {
426
+ return ResponsiveAlertDialog (
427
+ title: Text (AppLocalizations .of (context).board),
428
+ constraints: const BoxConstraints (maxWidth: LeapBreakpoints .compact),
429
+ content: BlocBuilder <EditorCubit , SetonixData >(
430
+ builder: (context, state) {
431
+ final board = _value == null ? null : state.getBoard (_value! .name);
432
+ return ListView (
433
+ shrinkWrap: true ,
434
+ children: [
435
+ DropdownMenu <String >(
436
+ dropdownMenuEntries: state.getBoards ().map ((e) {
437
+ return DropdownMenuEntry (
438
+ value: e,
439
+ label: e,
440
+ );
441
+ }).toList (),
442
+ label: Text (AppLocalizations .of (context).name),
443
+ initialSelection: _value? .name,
444
+ expandedInsets: EdgeInsets .all (8 ),
445
+ onSelected: (value) {
446
+ if (value == null ) return ;
447
+ setState (() {
448
+ _value = BoardDeckDefinition (name: value);
449
+ });
450
+ },
451
+ ),
452
+ if (board != null ) ...[
453
+ const SizedBox (height: 8 ),
454
+ OffsetListTile (
455
+ title: Text (AppLocalizations .of (context).position),
456
+ value: _value! .position.toOffset (),
457
+ onChanged: (value) {
458
+ setState (() {
459
+ _value = BoardDeckDefinition (
460
+ name: _value! .name,
461
+ position: value.toDefinition (),
462
+ );
463
+ });
464
+ },
465
+ ),
466
+ ],
467
+ ],
468
+ );
469
+ },
470
+ ),
471
+ actions: [
472
+ TextButton (
473
+ onPressed: () {
474
+ Navigator .of (context).pop ();
475
+ },
476
+ child: Text (AppLocalizations .of (context).cancel),
477
+ ),
478
+ ElevatedButton (
479
+ onPressed: () {
480
+ Navigator .of (context).pop (_value);
481
+ },
482
+ child: Text (AppLocalizations .of (context).save),
483
+ ),
484
+ ],
485
+ );
486
+ }
487
+ }
0 commit comments