mchess-client/lib/chess/chess_board.dart
Marco b9d574f2ab Fix 1-pixel lines between squares
In window widths or heigths that are not divisible by 8, the chess board
would contain lines between the squares (since the contraints of the
chess board rows would contain non-integer constraints).

With this commit, we calculate margins manually, in order to constrict
the chess board to widths and heights that are divisible by 8.
2023-08-22 04:24:30 +02:00

120 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)) {
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);
}
}