144 lines
4.5 KiB
Dart
144 lines
4.5 KiB
Dart
|
import 'package:flex_color_picker/flex_color_picker.dart';
|
||
|
import 'package:flutter/material.dart';
|
||
|
|
||
|
import '../data/models/pixel.dart';
|
||
|
import 'widgets/pixel_painter.dart';
|
||
|
|
||
|
class MatrixScreen extends StatefulWidget {
|
||
|
const MatrixScreen({super.key});
|
||
|
|
||
|
@override
|
||
|
State<MatrixScreen> createState() => _MatrixScreenState();
|
||
|
}
|
||
|
|
||
|
class _MatrixScreenState extends State<MatrixScreen> {
|
||
|
List<Pixel> pixels = List.generate(
|
||
|
64,
|
||
|
(index) => Pixel(
|
||
|
offset: Offset.zero,
|
||
|
color: Colors.transparent,
|
||
|
),
|
||
|
);
|
||
|
Color color = Colors.green;
|
||
|
|
||
|
void _updatePixel(Offset offset) {
|
||
|
const double cellSize = 50; // Size of each grid cell
|
||
|
|
||
|
// Get the row and column based on touch position
|
||
|
int row = (offset.dy / cellSize).floor();
|
||
|
int col = (offset.dx / cellSize).floor();
|
||
|
|
||
|
// Bound Check (Only proceed if within the grid)
|
||
|
if (row >= 0 && row < 8 && col >= 0 && col < 8) {
|
||
|
// Calculate the index in the flat list
|
||
|
int index = row * 8 + col;
|
||
|
|
||
|
// Update the Pixel
|
||
|
pixels[index] = Pixel(offset: offset, color: color);
|
||
|
setState(() {});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return Center(
|
||
|
child: Row(
|
||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||
|
children: [
|
||
|
Listener(
|
||
|
onPointerDown: (event) {
|
||
|
// Determine offset
|
||
|
Offset offset =
|
||
|
Offset(event.localPosition.dx, event.localPosition.dy);
|
||
|
|
||
|
// Calculate index and update pixel
|
||
|
_updatePixel(offset);
|
||
|
},
|
||
|
onPointerMove: (event) {
|
||
|
// Determine offset
|
||
|
Offset offset =
|
||
|
Offset(event.localPosition.dx, event.localPosition.dy);
|
||
|
|
||
|
// Calculate index and update pixel
|
||
|
_updatePixel(offset);
|
||
|
},
|
||
|
child: InteractiveViewer(
|
||
|
maxScale: 5,
|
||
|
child: Container(
|
||
|
// color: Colors.white,
|
||
|
decoration: BoxDecoration(border: Border.all()),
|
||
|
child: ClipRRect(
|
||
|
child: GridPaper(
|
||
|
divisions: 2,
|
||
|
interval: 500,
|
||
|
color: Theme.of(context).textTheme.headlineLarge?.color ??
|
||
|
Colors.red,
|
||
|
child: Transform(
|
||
|
transform: Matrix4.identity()..scale(50.0),
|
||
|
child: ClipRect(
|
||
|
child: CustomPaint(
|
||
|
size: const Size(400, 400),
|
||
|
painter: PixelPainter(
|
||
|
pixels: pixels,
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
const SizedBox(
|
||
|
width: 24,
|
||
|
),
|
||
|
ColorIndicator(
|
||
|
width: 40,
|
||
|
height: 40,
|
||
|
borderRadius: 24,
|
||
|
color: color,
|
||
|
elevation: 1,
|
||
|
onSelectFocus: false,
|
||
|
onSelect: () async {
|
||
|
// Wait for the dialog to return color selection result.
|
||
|
final Color newColor = await showColorPickerDialog(
|
||
|
context,
|
||
|
color,
|
||
|
title: Text('ColorPicker',
|
||
|
style: Theme.of(context).textTheme.titleLarge),
|
||
|
width: 40,
|
||
|
height: 40,
|
||
|
spacing: 0,
|
||
|
runSpacing: 0,
|
||
|
borderRadius: 0,
|
||
|
wheelDiameter: 165,
|
||
|
enableOpacity: true,
|
||
|
showColorCode: true,
|
||
|
colorCodeHasColor: true,
|
||
|
pickersEnabled: <ColorPickerType, bool>{
|
||
|
ColorPickerType.wheel: true,
|
||
|
},
|
||
|
copyPasteBehavior: const ColorPickerCopyPasteBehavior(
|
||
|
copyButton: true,
|
||
|
pasteButton: true,
|
||
|
longPressMenu: true,
|
||
|
),
|
||
|
actionButtons: const ColorPickerActionButtons(
|
||
|
okButton: true,
|
||
|
closeButton: true,
|
||
|
dialogActionButtons: false,
|
||
|
),
|
||
|
constraints: const BoxConstraints(
|
||
|
minHeight: 480, minWidth: 320, maxWidth: 320),
|
||
|
);
|
||
|
// Update the state with the newly selected color from the color picker
|
||
|
setState(() {
|
||
|
color = newColor;
|
||
|
});
|
||
|
}),
|
||
|
],
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|