121 lines
3.6 KiB
Dart
121 lines
3.6 KiB
Dart
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<ChessSquare> squares;
|
|
|
|
const ChessBoard._({required this.bState, required this.squares});
|
|
|
|
factory ChessBoard({required ChessBoardState boardState}) {
|
|
List<ChessSquare> 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.positionAckdByServer) {
|
|
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<Row> chessBoard = <Row>[];
|
|
|
|
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);
|
|
}
|
|
}
|