tablet-app/lib/Screens/Puzzle/puzzle_view.dart

195 lines
6.3 KiB
Dart

import 'dart:convert';
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:manager_api/api.dart';
import 'package:provider/provider.dart';
import 'package:tablet_app/Components/loading_common.dart';
import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/Screens/Puzzle/message_dialog.dart';
import 'package:tablet_app/app_context.dart';
import 'puzzle_piece.dart';
import 'score_widget.dart';
const IMAGE_PATH = 'image_path';
class PuzzleView extends StatefulWidget {
final SectionDTO? section;
PuzzleView({this.section});
@override
_PuzzleView createState() => _PuzzleView();
}
class _PuzzleView extends State<PuzzleView> {
PuzzleDTO puzzleDTO = PuzzleDTO();
int allInPlaceCount = 0;
bool isFinished = false;
GlobalKey _widgetKey = GlobalKey();
Size? realWidgetSize;
//File? _image;
String? _imagePath;
List<Widget> pieces = [];
bool isSplittingImage = true;
@override
void initState() {
puzzleDTO = PuzzleDTO.fromJson(jsonDecode(widget.section!.data!))!;
puzzleDTO.rows = puzzleDTO.rows != null ? puzzleDTO.rows : 3;
puzzleDTO.cols = puzzleDTO.cols != null ? puzzleDTO.cols : 3;
WidgetsBinding.instance.addPostFrameCallback((_) {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context, listen: false);
TabletAppContext tabletAppContext = appContext.getContext();
TranslationAndResourceDTO? messageDebut = puzzleDTO.messageDebut != null ? puzzleDTO.messageDebut!.firstWhere((message) => message.language!.toUpperCase() == tabletAppContext.language!.toUpperCase()) : null;
if(messageDebut != null) {
showMessage(messageDebut, appContext, context, size);
}
getRealWidgetSize();
});
super.initState();
if(puzzleDTO.image != null && puzzleDTO.image!.resourceUrl != null) {
splitImage(Image.network(puzzleDTO.image!.resourceUrl!));
}
}
Future<void> getRealWidgetSize() async {
RenderBox renderBox = _widgetKey.currentContext?.findRenderObject() as RenderBox;
Size size = renderBox.size;
setState(() {
realWidgetSize = size;
});
print("Taille réelle du widget : $size");
}
// we need to find out the image size, to be used in the PuzzlePiece widget
Future<Size> getImageSize(Image image) async {
final Completer<Size> completer = Completer<Size>();
image.image
.resolve(const ImageConfiguration())
.addListener(ImageStreamListener((ImageInfo info, bool _) {
completer.complete(
Size(info.image.width.toDouble(), info.image.height.toDouble()));
}));
final Size imageSize = await completer.future;
return imageSize;
}
// here we will split the image into small pieces
// using the rows and columns defined above; each piece will be added to a stack
void splitImage(Image image) async {
Size imageSize = await getImageSize(image);
//imageSize = realWidgetSize!;
imageSize = Size(realWidgetSize!.width * 1.25, realWidgetSize!.height * 1.25);
for (int x = 0; x < puzzleDTO.rows!; x++) {
for (int y = 0; y < puzzleDTO.cols!; y++) {
setState(() {
pieces.add(
PuzzlePiece(
key: GlobalKey(),
image: image,
imageSize: imageSize,
row: x,
col: y,
maxRow: puzzleDTO.rows!,
maxCol: puzzleDTO.cols!,
bringToTop: this.bringToTop,
sendToBack: this.sendToBack,
),
);
});
}
}
setState(() {
isSplittingImage = false;
});
}
// when the pan of a piece starts, we need to bring it to the front of the stack
void bringToTop(Widget widget) {
setState(() {
pieces.remove(widget);
pieces.add(widget);
});
}
// when a piece reaches its final position,
// it will be sent to the back of the stack to not get in the way of other, still movable, pieces
void sendToBack(Widget widget) {
setState(() {
allInPlaceCount++;
isFinished = allInPlaceCount == puzzleDTO.rows! * puzzleDTO.cols!;
pieces.remove(widget);
pieces.insert(0, widget);
if(isFinished) {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context, listen: false);
TabletAppContext tabletAppContext = appContext.getContext();
TranslationAndResourceDTO? messageFin = puzzleDTO.messageFin != null ? puzzleDTO.messageFin!.firstWhere((message) => message.language!.toUpperCase() == tabletAppContext.language!.toUpperCase()) : null;
if(messageFin != null) {
showMessage(messageFin, appContext, context, size);
}
}
});
}
@override
Widget build(BuildContext context) {
final appContext = Provider.of<AppContext>(context);
TabletAppContext tabletAppContext = appContext.getContext();
return Padding(
key: _widgetKey,
padding: const EdgeInsets.all(10.0),
child: isSplittingImage ? Center(child: LoadingCommon()) :
puzzleDTO.image!.resourceUrl == null || realWidgetSize == null
? Container(
width: 50,
height: 50,
color: Colors.cyan,
child: InkWell(onTap: () {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context, listen: false);
TabletAppContext tabletAppContext = appContext.getContext();
TranslationAndResourceDTO? messageFin = puzzleDTO.messageFin != null ? puzzleDTO.messageFin!.firstWhere((message) => message.language!.toUpperCase() == tabletAppContext.language!.toUpperCase()) : null;
if(messageFin != null) {
// Alert dialog
showMessage(messageFin, appContext, context, size);
}
},),)//Center(child: Text("Invalid image"))
: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: tabletAppContext.puzzleSize != null ? tabletAppContext.puzzleSize!.width : realWidgetSize!.width * 0.8,
height: tabletAppContext.puzzleSize != null ? tabletAppContext.puzzleSize!.height +1.5 : realWidgetSize!.height * 0.8,
child: Stack(
children: pieces,
),
),
),
),
);
}
}