diff --git a/lib/stateManagement/openFiles/types/McdFileData.dart b/lib/stateManagement/openFiles/types/McdFileData.dart index 1ffa562..07f355a 100644 --- a/lib/stateManagement/openFiles/types/McdFileData.dart +++ b/lib/stateManagement/openFiles/types/McdFileData.dart @@ -473,6 +473,23 @@ class McdParagraph extends _McdFilePart { fontId.restoreWith(paragraph.fontId); lines.restoreWith(paragraph.lines); } + + Map toJson() { + return { + "fontId": fontId.value, + "lines": lines.map((l) => l.text.value).toList(), + }; + } + + McdParagraph.fromJson(super.file, Map json) : + fontId = NumberProp(json["fontId"], true, fileId: file), + lines = ValueListNotifier( + (json["lines"] as List).map((l) => McdLine(file, StringProp(l, fileId: file))).toList(), + fileId: file + ) { + fontId.addListener(onDataChanged); + lines.addListener(onDataChanged); + } } class McdEvent extends _McdFilePart { @@ -546,6 +563,20 @@ class McdEvent extends _McdFilePart { name.restoreWith(event.name); paragraphs.restoreWith(event.paragraphs); } + + List toJson() { + return paragraphs.map((p) => p.toJson()).toList(); + } + + McdEvent.fromJson(super.file, String name, List paragraphs) : + name = StringProp(name, fileId: file), + paragraphs = ValueListNotifier( + paragraphs.map((p) => McdParagraph.fromJson(file, p)).toList(), + fileId: file + ) { + this.name.addListener(onDataChanged); + this.paragraphs.addListener(onDataChanged); + } } class McdData extends _McdFilePart { @@ -1165,6 +1196,20 @@ class McdData extends _McdFilePart { .toSet(); } + Map toJson() { + return { + for (var event in events) + event.name.value: event.toJson() + }; + } + + void fromJson(Map json) { + events.clear(); + for (var entry in json.entries) { + events.add(McdEvent.fromJson(file, entry.key, entry.value)); + } + } + @override Undoable takeSnapshot() { var snapshot = McdData( diff --git a/lib/widgets/filesView/types/fonts/mcdEditor.dart b/lib/widgets/filesView/types/fonts/mcdEditor.dart index f593bb0..34d7f16 100644 --- a/lib/widgets/filesView/types/fonts/mcdEditor.dart +++ b/lib/widgets/filesView/types/fonts/mcdEditor.dart @@ -1,7 +1,11 @@ +import 'dart:convert'; +import 'dart:io'; import 'dart:math'; +import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:path/path.dart'; import 'package:tuple/tuple.dart'; import '../../../../stateManagement/Property.dart'; @@ -58,9 +62,9 @@ class _McdEditorState extends ChangeNotifierState { const SizedBox(height: 35), Row( children: [ - _makeTabButton(0, "MCD Events"), - _makeTabButton(1, "Font overrides"), - _makeTabButton(2, "Font debugger"), + _makeTabButton(context, 0, "MCD Events"), + _makeTabButton(context, 1, "Font overrides"), + _makeTabButton(context, 2, "Font debugger"), const SizedBox(width: 12), Container( width: 1, @@ -70,6 +74,36 @@ class _McdEditorState extends ChangeNotifierState { ), ), const FontOverridesApplyButton(), + const SizedBox(width: 12), + PopupMenuButton( + icon: const Icon(Icons.more_vert), + splashRadius: 26, + tooltip: "", + onSelected: (String? newValue) { + if (newValue == "E JSON") + saveAsJson(); + else if (newValue == "I JSON") + loadFromJson(); + else + throw Exception("Unknown export type: $newValue"); + }, + itemBuilder: (context) => [ + const PopupMenuItem( + value: "E JSON", + child: ListTile( + leading: Icon(Icons.upload), + title: Text("Export as JSON"), + ), + ), + const PopupMenuItem( + value: "I JSON", + child: ListTile( + leading: Icon(Icons.download), + title: Text("Import from JSON"), + ), + ), + ], + ) ] ), const Divider(height: 1,), @@ -91,7 +125,7 @@ class _McdEditorState extends ChangeNotifierState { ); } - Widget _makeTabButton(int index, String text) { + Widget _makeTabButton(BuildContext context, int index, String text) { return Flexible( child: SizedBox( width: 175, @@ -118,6 +152,32 @@ class _McdEditorState extends ChangeNotifierState { ), ); } + + void saveAsJson() async { + var path = await FilePicker.platform.saveFile( + dialogTitle: "Save MCD as JSON", + type: FileType.custom, + allowedExtensions: ["json"], + fileName: "${basename(widget.file.path)}.json", + ); + if (path == null) + return; + var json = widget.file.mcdData!.toJson(); + var jsonStr = const JsonEncoder.withIndent(" ").convert(json); + await File(path).writeAsString(jsonStr); + } + + void loadFromJson() async { + var result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: ["json"], + ); + if (result == null) + return; + var jsonStr = await File(result.files.single.path!).readAsString(); + var json = jsonDecode(jsonStr); + widget.file.mcdData!.fromJson(json); + } } class _MovingEvent {