import 'dart:developer'; import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:mchess/chess_bloc/chess_bloc.dart'; import 'chess_square.dart'; import '../utils/chess_utils.dart'; class ChessBoard extends StatelessWidget { final ChessBoardState bState; final List squares; const ChessBoard._({required this.bState, required this.squares}); factory ChessBoard({required ChessBoardState boardState}) { List squares = List.empty(growable: true); for (int i = 0; i < 64; i++) { var column = (i % 8) + 1; var row = (i ~/ 8) + 1; final piece = boardState.position[ChessCoordinate(column, row)]; bool squareWasPartOfLastMove = false; if ((boardState.lastMove.to == ChessCoordinate(column, row) || boardState.lastMove.from == ChessCoordinate(column, row)) && boardState.positionAckd) { squareWasPartOfLastMove = true; } squares.add( ChessSquare( ChessCoordinate(column, row), piece, squareWasPartOfLastMove, ), ); } return ChessBoard._(bState: boardState, squares: squares); } @override Widget build(BuildContext context) { log("ChessBoard's build()"); return LayoutBuilder(builder: (context, constraints) { /*We calculate the margins manually, because otherwise we would have lines that are 1 pixel wide between the squares (which is ugly)*/ int smallerSize = math.min(constraints.maxWidth.toInt(), constraints.maxHeight.toInt()); int desiredSize = smallerSize - smallerSize % 8; int verticalMargin = constraints.maxHeight.toInt() - desiredSize; int verticalMarginTop = verticalMargin ~/ 2; int verticalMarginBottom = verticalMargin - verticalMarginTop; int horizontalMargin = constraints.maxWidth.toInt() - desiredSize; int horizontalMarginLeft = horizontalMargin ~/ 2; int horizontalMarginRight = horizontalMargin - horizontalMarginLeft; return Container( margin: EdgeInsets.only( left: horizontalMarginLeft.toDouble(), right: horizontalMarginRight.toDouble(), top: verticalMarginTop.toDouble(), bottom: verticalMarginBottom.toDouble(), ), child: FittedBox( fit: BoxFit.contain, child: Container( decoration: const BoxDecoration(boxShadow: [ BoxShadow(color: Colors.black, offset: Offset(10, 10)) ]), child: _buildBoard(bState.bottomColor == ChessColor.black), ), ), ); }); } Row _buildChessRow(int rowNo, bool flipped) { if (!flipped) { return Row( children: [ for (int i = 8 * rowNo - 8; i < 8 * rowNo; i++) squares.elementAt(i) ], ); } else { return Row( children: [ for (int i = 8 * rowNo - 1; i >= 8 * rowNo - 8; i--) squares.elementAt(i) ], ); } } Column _buildBoard(bool flipped) { List chessBoard = []; if (!flipped) { for (int row = 8; row > 0; row--) { chessBoard.add(_buildChessRow(row, flipped)); } } else { for (int row = 1; row <= 8; row++) { chessBoard.add(_buildChessRow(row, flipped)); } } return Column(children: [...chessBoard]); } ChessSquare getSquareAtCoordinate(ChessCoordinate coord) { /* Calculate index in squares[] from column and row */ int index = (coord.row - 1) * 8 + (coord.column - 1); log("getSquareAtCoordinates: index calculated to $index"); return squares.elementAt(index); } }