Skip to content
Snippets Groups Projects
cell.dart 5.81 KiB
Newer Older
Benoît Harrault's avatar
Benoît Harrault committed
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';

import 'package:suguru/config/application_config.dart';

import 'package:suguru/cubit/activity/activity_cubit.dart';
import 'package:suguru/models/activity/cell.dart';
import 'package:suguru/models/activity/activity.dart';

class CellWidget extends StatelessWidget {
  const CellWidget({
    super.key,
    required this.cell,
    required this.hasBlockBorderTop,
    required this.hasBlockBorderLeft,
    required this.hasBlockBorderBottom,
    required this.hasBlockBorderRight,
  });

  final Cell cell;
  final bool hasBlockBorderTop;
  final bool hasBlockBorderLeft;
  final bool hasBlockBorderBottom;
  final bool hasBlockBorderRight;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<ActivityCubit, ActivityState>(
      builder: (BuildContext context, ActivityState activityState) {
        final Activity activity = activityState.currentActivity;

        final String imageAsset = getImageAssetName(activity);

        return Container(
          decoration: BoxDecoration(
            color: getBackgroundColor(activity),
            border: getCellBorders(activity),
          ),
          child: GestureDetector(
            child: AnimatedSwitcher(
              duration: const Duration(milliseconds: 100),
              transitionBuilder: (Widget child, Animation<double> animation) {
                return ScaleTransition(scale: animation, child: child);
              },
              child: Image(
                image: AssetImage(imageAsset),
                fit: BoxFit.fill,
                key: ValueKey<int>(imageAsset.hashCode),
              ),
            ),
            onTap: () {
              final ActivityCubit activityCubit = BlocProvider.of<ActivityCubit>(context);

              if (cell.location.col != activity.selectedCell?.location.col ||
                  cell.location.row != activity.selectedCell?.location.row) {
                activityCubit.selectCell(cell.location);
              } else {
                activityCubit.unselectCell();
              }
            },
          ),
        );
      },
    );
  }

  /*
  * Compute image asset name, from skin and cell value/state
  */
  String getImageAssetName(Activity activity) {
    if (cell.value > 0 && cell.value < 10) {
      return 'assets/skins/${activity.activitySettings.get(ApplicationConfig.parameterCodeSkin)}_${cell.value}.png';
    }

    return 'assets/ui/cell_empty.png';
  }

  // Compute cell background color, from cell state
  Color getBackgroundColor(Activity activity) {
    final Color editableCellColor = Colors.grey.shade100;
    final Color editableCellColorConflict = Colors.pink.shade100;
    final Color fixedCellColor = Colors.grey.shade300;
    final Color fixedCellColorConflict = Colors.pink.shade200;
    final Color editableAnimated = Colors.green.shade200;
    final Color fixedAnimated = Colors.green.shade300;

    Color backgroundColor = editableCellColor;

    if (cell.isFixed == true) {
      backgroundColor = fixedCellColor;
    }

    final int conflictsCount = activity.boardConflicts[cell.location.row][cell.location.col];

    if (activity.showConflicts == true) {
      if (conflictsCount != 0) {
        if (cell.isFixed == true) {
          backgroundColor = fixedCellColorConflict;
        } else {
          backgroundColor = editableCellColorConflict;
        }
      }
    }

    final bool isAnimated = activity.boardAnimated[cell.location.row][cell.location.col];

    if (isAnimated) {
      if (cell.isFixed == true) {
        backgroundColor = fixedAnimated;
      } else {
        backgroundColor = editableAnimated;
      }
    }

    return backgroundColor;
  }

  // Compute cell borders, from board size and cell state
  Border getCellBorders(Activity activity) {
    final Color cellBorderDarkColor = Colors.grey.shade800;
    final Color cellBorderLightColor = Colors.grey.shade400;
    const Color cellBorderSelectedColor = Colors.red;

    Color cellBorderColor = cellBorderSelectedColor;
    double cellBorderWidth = 4;

    final int boardSizeReference =
        max(activity.boardSizeHorizontal, activity.boardSizeVertical);

    // Reduce cell border width on big boards
    if (boardSizeReference > 8) {
      cellBorderWidth = 2;
      if (boardSizeReference > 10) {
        cellBorderWidth = 1;
      }
    }

    if (!activity.isRunning) {
      cellBorderColor = Colors.green.shade700;
    }

    Border borders = Border.all(
      color: cellBorderColor,
      width: cellBorderWidth,
    );

    // Update cell borders if not currently selected cell
    if (cell.location.col != activity.selectedCell?.location.col ||
        cell.location.row != activity.selectedCell?.location.row) {
      borders = Border(
        top: BorderSide(
            width: cellBorderWidth,
            color: (hasBlockBorderTop ||
                    (((cell.location.row) % activity.boardSizeVertical) == 0))
                ? cellBorderDarkColor
                : cellBorderLightColor),
        left: BorderSide(
            width: cellBorderWidth,
            color: (hasBlockBorderLeft ||
                    (((cell.location.col) % activity.boardSizeHorizontal) == 0))
                ? cellBorderDarkColor
                : cellBorderLightColor),
        right: BorderSide(
            width: cellBorderWidth,
            color: (hasBlockBorderRight ||
                    ((((cell.location.col) + 1) % activity.boardSizeHorizontal) == 0))
                ? cellBorderDarkColor
                : cellBorderLightColor),
        bottom: BorderSide(
            width: cellBorderWidth,
            color: (hasBlockBorderBottom ||
                    ((((cell.location.row) + 1) % activity.boardSizeVertical) == 0))
                ? cellBorderDarkColor
                : cellBorderLightColor),
      );
    }

    return borders;
  }
}