diff --git a/lib/bademagic_module/utils/badge_utils.dart b/lib/bademagic_module/utils/badge_utils.dart new file mode 100644 index 000000000..90d1a3b6a --- /dev/null +++ b/lib/bademagic_module/utils/badge_utils.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +class BadgeUtils { + MapEntry getBadgeOffsetBackground(Size size) { + var paddingPercentage = 5.0; + var offsetHeightBadgeBackground = (paddingPercentage / 100) * size.height; + var offsetWidthBadgeBackground = (paddingPercentage / 100) * size.width; + return MapEntry(offsetHeightBadgeBackground, offsetWidthBadgeBackground); + } + + MapEntry getBadgeSize(double offsetHeightBadgeBackground, + double offsetWidthBadgeBackground, Size size) { + var badgeHeight = size.height - (2 * offsetHeightBadgeBackground); + var badgeWidth = size.width - (2 * offsetWidthBadgeBackground); + return MapEntry(badgeHeight, badgeWidth); + } + + MapEntry getCellStartCoordinate( + double offsetWidthBadgeBackground, + double offsetHeightBadgeBackground, + double badgeWidth, + double badgeHeight) { + { + var cellSize = badgeWidth / 44; + + // Calculate offsets to center the cells within the rectangle + double totalCellsWidth = (cellSize * 0.92) * 44; + double totalCellsHeight = cellSize * 11; + + var cellStartX = + offsetWidthBadgeBackground + (badgeWidth - totalCellsWidth) / 2; + var cellStartY = + offsetHeightBadgeBackground + (badgeHeight - totalCellsHeight) / 2; + + return MapEntry(cellStartX, cellStartY); + } + } +} diff --git a/lib/view/draw_badge_screen.dart b/lib/view/draw_badge_screen.dart index b213a2ce9..a7fb9dc5b 100644 --- a/lib/view/draw_badge_screen.dart +++ b/lib/view/draw_badge_screen.dart @@ -7,7 +7,6 @@ import 'package:badgemagic/view/widgets/common_scaffold_widget.dart'; import 'package:badgemagic/virtualbadge/view/draw_badge.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; class DrawBadge extends StatefulWidget { final String? filename; @@ -52,132 +51,144 @@ class _DrawBadgeState extends State { return CommonScaffold( index: 1, title: 'BadgeMagic', - body: Padding( - padding: EdgeInsets.only(top: 20.h, right: 20.w, left: 20.w), - child: Column( - children: [ - Container( - padding: EdgeInsets.only( - top: 37.h, left: 32.h, right: 30.h, bottom: 30.h), - height: 400.h, - width: 500.w, - decoration: BoxDecoration( - color: Colors.black, - border: Border.all(color: Colors.black), - borderRadius: BorderRadius.circular(10), + body: SingleChildScrollView( + physics: NeverScrollableScrollPhysics(), + key: const Key(drawBadgeScreen), + child: Align( + alignment: Alignment.center, + child: LayoutBuilder( + builder: (context, constraints) => Container( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth * 0.94, ), - child: BMBadge( - providerInit: (provider) => drawToggle = provider, - badgeGrid: widget.badgeGrid - ?.map((e) => e.map((e) => e == 1).toList()) - .toList(), - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - TextButton( - onPressed: () { - setState(() { - drawToggle.toggleIsDrawing(true); - }); - }, - child: Column( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( children: [ - Icon( - Icons.edit, - color: drawToggle.getIsDrawing() - ? Colors.red - : Colors.black, + SizedBox( + width: 100, + ), + BMBadge( + providerInit: (provider) => drawToggle = provider, + badgeGrid: widget.badgeGrid + ?.map((e) => e.map((e) => e == 1).toList()) + .toList(), ), - Text( - 'Draw', - style: TextStyle( - color: - drawToggle.isDrawing ? Colors.red : Colors.black, - ), - ) ], ), - ), - TextButton( - onPressed: () { - setState(() { - drawToggle.toggleIsDrawing(false); - }); - }, - child: Column( + Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - Icons.delete, - color: drawToggle.isDrawing ? Colors.black : Colors.red, + TextButton( + onPressed: () { + setState(() { + drawToggle.toggleIsDrawing(true); + }); + }, + child: Column( + children: [ + Icon( + Icons.edit, + color: drawToggle.getIsDrawing() + ? Colors.red + : Colors.black, + ), + Text( + 'Draw', + style: TextStyle( + color: drawToggle.isDrawing + ? Colors.red + : Colors.black, + ), + ) + ], + ), ), - Text( - 'Erase', - style: TextStyle( - color: - drawToggle.isDrawing ? Colors.black : Colors.red, + TextButton( + onPressed: () { + setState(() { + drawToggle.toggleIsDrawing(false); + }); + }, + child: Column( + children: [ + Icon( + Icons.delete, + color: drawToggle.isDrawing + ? Colors.black + : Colors.red, + ), + Text( + 'Erase', + style: TextStyle( + color: drawToggle.isDrawing + ? Colors.black + : Colors.red, + ), + ) + ], ), - ) - ], - ), - ), - TextButton( - onPressed: () { - setState(() { - drawToggle.resetDrawViewGrid(); - }); - }, - child: const Column( - children: [ - Icon( - Icons.refresh, - color: Colors.black, ), - Text( - 'Reset', - style: TextStyle(color: Colors.black), - ) - ], - ), - ), - TextButton( - onPressed: () { - List> badgeGrid = drawToggle - .getDrawViewGrid() - .map((e) => e.map((e) => e ? 1 : 0).toList()) - .toList(); - List hexString = - Converters.convertBitmapToLEDHex(badgeGrid, false); - widget.isSavedCard! - ? fileHelper.updateBadgeText( - widget.filename!, - hexString, - ) - : widget.isSavedClipart! - ? fileHelper.updateClipart( - widget.filename!, badgeGrid) - : fileHelper - .saveImage(drawToggle.getDrawViewGrid()); - fileHelper.generateClipartCache(); - ToastUtils().showToast("Clipart Saved Successfully"); - }, - child: const Column( - children: [ - Icon( - Icons.save, - color: Colors.black, + TextButton( + onPressed: () { + setState(() { + drawToggle.resetDrawViewGrid(); + }); + }, + child: const Column( + children: [ + Icon( + Icons.refresh, + color: Colors.black, + ), + Text( + 'Reset', + style: TextStyle(color: Colors.black), + ) + ], + ), + ), + TextButton( + onPressed: () { + List> badgeGrid = drawToggle + .getDrawViewGrid() + .map((e) => e.map((e) => e ? 1 : 0).toList()) + .toList(); + List hexString = + Converters.convertBitmapToLEDHex( + badgeGrid, false); + widget.isSavedCard! + ? fileHelper.updateBadgeText( + widget.filename!, + hexString, + ) + : widget.isSavedClipart! + ? fileHelper.updateClipart( + widget.filename!, badgeGrid) + : fileHelper + .saveImage(drawToggle.getDrawViewGrid()); + fileHelper.generateClipartCache(); + ToastUtils().showToast("Clipart Saved Successfully"); + }, + child: const Column( + children: [ + Icon( + Icons.save, + color: Colors.black, + ), + Text('Save', style: TextStyle(color: Colors.black)) + ], + ), ), - Text('Save', style: TextStyle(color: Colors.black)) ], ), - ), - ], - ) - ], + ], + ), + ), + ), ), ), - key: const Key(drawBadgeScreen), ); } } diff --git a/lib/view/homescreen.dart b/lib/view/homescreen.dart index e306cb668..ce87e1888 100644 --- a/lib/view/homescreen.dart +++ b/lib/view/homescreen.dart @@ -1,4 +1,5 @@ import 'dart:async'; + import 'package:badgemagic/bademagic_module/utils/byte_array_utils.dart'; import 'package:badgemagic/bademagic_module/utils/converters.dart'; import 'package:badgemagic/bademagic_module/utils/image_utils.dart'; @@ -147,207 +148,181 @@ class _HomeScreenState extends State index: 0, title: 'BadgeMagic', body: SafeArea( - child: Stack( - children: [ - SingleChildScrollView( - physics: isDialInteracting - ? const NeverScrollableScrollPhysics() - : const AlwaysScrollableScrollPhysics(), - child: Column( - children: [ - SizedBox( - height: 120.h, - ), - Container( - margin: EdgeInsets.all(15.w), - child: Material( - color: Colors.white, - borderRadius: BorderRadius.circular(10.r), - elevation: 4, - child: ExtendedTextField( - onChanged: (value) {}, - controller: inlineimagecontroller, - specialTextSpanBuilder: ImageBuilder(), - decoration: InputDecoration( - hintText: errorVal, - hintStyle: TextStyle(color: Colors.red), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.r), - ), - prefixIcon: IconButton( - onPressed: () { - setState(() { - isPrefixIconClicked = - !isPrefixIconClicked; - }); - }, - icon: const Icon(Icons.tag_faces_outlined), - ), - focusedBorder: const OutlineInputBorder( - borderSide: BorderSide(color: Colors.red), - ), - ), + child: SingleChildScrollView( + physics: isDialInteracting + ? const NeverScrollableScrollPhysics() + : const AlwaysScrollableScrollPhysics(), + child: Column( + children: [ + AnimationBadge(), + Container( + margin: EdgeInsets.all(15.w), + child: Material( + color: Colors.white, + borderRadius: BorderRadius.circular(10.r), + elevation: 4, + child: ExtendedTextField( + onChanged: (value) {}, + controller: inlineimagecontroller, + specialTextSpanBuilder: ImageBuilder(), + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.r), + ), + prefixIcon: IconButton( + onPressed: () { + setState(() { + isPrefixIconClicked = !isPrefixIconClicked; + }); + }, + icon: const Icon(Icons.tag_faces_outlined), + ), + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.red), ), ), ), - Visibility( - visible: isPrefixIconClicked, - child: Container( - height: 150.h, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.r), - color: Colors.grey.shade100, + ), + ), + Visibility( + visible: isPrefixIconClicked, + child: Container( + height: 150.h, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.r), + color: Colors.grey.shade100, + ), + margin: EdgeInsets.symmetric(horizontal: 15.w), + padding: EdgeInsets.symmetric( + vertical: 10.h, horizontal: 10.w), + child: VectorGridView())), + TabBar( + indicatorSize: TabBarIndicatorSize.label, + labelColor: Colors.black, + unselectedLabelColor: Colors.grey, + indicatorColor: Colors.red, + controller: _tabController, + splashFactory: InkRipple.splashFactory, + overlayColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.pressed)) { + return Colors.grey[300]; + } + return null; + }, + ), + tabs: const [ + Tab(text: 'Speed'), + Tab(text: 'Animation'), + Tab(text: 'Effects'), + ], + ), + SizedBox( + height: 180.h, // Adjust the height dynamically + child: TabBarView( + physics: const NeverScrollableScrollPhysics(), + controller: _tabController, + children: [ + GestureDetector( + onPanDown: (_) { + // Enter interaction mode to stop main scrolling + setState(() => isDialInteracting = true); + }, + onPanCancel: () { + // Exit interaction mode if interaction is cancelled + setState(() => isDialInteracting = false); + }, + onPanEnd: (_) { + // Re-enable main scroll when done interacting + setState(() => isDialInteracting = false); + }, + child: RadialDial()), + AnimationTab(), + EffectTab(), + ], + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 20.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + onTap: () { + logger.i( + 'Save button clicked, showing dialog : ${animationProvider.isEffectActive(FlashEffect())}'); + showDialog( + context: this.context, + builder: (context) { + return SaveBadgeDialog( + speed: speedDialProvider, + animationProvider: animationProvider, + textController: inlineImageProvider + .getController(), + isInverse: + animationProvider.isEffectActive( + InvertLEDEffect()), + ); + }); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 33.w, vertical: 8.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2.r), + color: Colors.grey.shade400, + ), + child: const Text('Save'), ), - margin: EdgeInsets.symmetric(horizontal: 15.w), - padding: EdgeInsets.symmetric( - vertical: 10.h, horizontal: 10.w), - child: VectorGridView())), - TabBar( - indicatorSize: TabBarIndicatorSize.label, - labelColor: Colors.black, - unselectedLabelColor: Colors.grey, - indicatorColor: Colors.red, - controller: _tabController, - splashFactory: InkRipple.splashFactory, - overlayColor: WidgetStateProperty.resolveWith( - (Set states) { - if (states.contains(WidgetState.pressed)) { - return Colors.grey[300]; - } - return null; - }, + ), + ], ), - tabs: const [ - Tab(text: 'Speed'), - Tab(text: 'Animation'), - Tab(text: 'Effects'), - ], ), SizedBox( - height: 180.h, // Adjust the height dynamically - child: TabBarView( - physics: const NeverScrollableScrollPhysics(), - controller: _tabController, + width: 100.w, + ), + Container( + padding: EdgeInsets.symmetric(vertical: 20.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( - onPanDown: (_) { - // Enter interaction mode to stop main scrolling - setState(() => isDialInteracting = true); - }, - onPanCancel: () { - // Exit interaction mode if interaction is cancelled - setState(() => isDialInteracting = false); - }, - onPanEnd: (_) { - // Re-enable main scroll when done interacting - setState(() => isDialInteracting = false); - }, - child: RadialDial()), - AnimationTab(), - EffectTab(), + onTap: () { + badgeData.checkAndTransfer( + inlineImageProvider.getController().text, + animationProvider + .isEffectActive(FlashEffect()), + animationProvider + .isEffectActive(MarqueeEffect()), + animationProvider + .isEffectActive(InvertLEDEffect()), + speedDialProvider.getOuterValue(), + modeValueMap[animationProvider + .getAnimationIndex()], + null, + false); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 20.w, vertical: 8.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2.r), + color: Colors.grey.shade400, + ), + child: const Text('Transfer'), + ), + ), ], ), ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - padding: EdgeInsets.symmetric(vertical: 20.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - GestureDetector( - onTap: () { - logger.i( - 'Save button clicked, showing dialog : ${animationProvider.isEffectActive(FlashEffect())}'); - inlineimagecontroller.text == "" - ? setState(() { - errorVal = - "Please fill out this field"; - }) - : { - setState(() { - errorVal = ""; - }), - showDialog( - context: this.context, - builder: (context) { - return SaveBadgeDialog( - speed: speedDialProvider, - animationProvider: - animationProvider, - textController: - inlineImageProvider - .getController(), - isInverse: animationProvider - .isEffectActive( - InvertLEDEffect()), - ); - }) - }; - }, - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 33.w, vertical: 8.h), - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(2.r), - color: Colors.grey.shade400, - ), - child: const Text('Save'), - ), - ), - ], - ), - ), - SizedBox( - width: 100.w, - ), - Container( - padding: EdgeInsets.symmetric(vertical: 20.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - GestureDetector( - onTap: () { - badgeData.checkAndTransfer( - inlineImageProvider - .getController() - .text, - animationProvider - .isEffectActive(FlashEffect()), - animationProvider - .isEffectActive(MarqueeEffect()), - animationProvider.isEffectActive( - InvertLEDEffect()), - speedDialProvider.getOuterValue(), - modeValueMap[animationProvider - .getAnimationIndex()], - null, - false); - }, - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 20.w, vertical: 8.h), - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(2.r), - color: Colors.grey.shade400, - ), - child: const Text('Transfer'), - ), - ), - ], - ), - ), - ], - ) ], - ), - ), - AnimationBadge(), - ], + ) + ], + ), ), ), scaffoldKey: const Key(homeScreenTitleKey), diff --git a/lib/virtualbadge/view/animated_badge.dart b/lib/virtualbadge/view/animated_badge.dart index 484c5dab2..e28805e49 100644 --- a/lib/virtualbadge/view/animated_badge.dart +++ b/lib/virtualbadge/view/animated_badge.dart @@ -1,7 +1,6 @@ import 'package:badgemagic/providers/animation_badge_provider.dart'; import 'package:badgemagic/virtualbadge/view/badge_paint.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:provider/provider.dart'; class AnimationBadge extends StatefulWidget { @@ -12,26 +11,66 @@ class AnimationBadge extends StatefulWidget { } class _AnimationBadgeState extends State { + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + context.read().initializeAnimation(); + }); + } + @override Widget build(BuildContext context) { - return Container( - margin: EdgeInsets.only(top: 8.h, left: 15.w, right: 15.w), - padding: EdgeInsets.all(8.dg), - height: 100.h, - width: 500.w, - decoration: BoxDecoration( - color: Colors.black, - border: Border.all(color: Colors.black), - borderRadius: BorderRadius.circular(10), + final provider = context.watch(); + return AspectRatio( + aspectRatio: 3.2, + child: CustomPaint( + painter: BadgePaint(grid: provider.getPaintGrid()), ), - child: Consumer( - builder: (context, provider, widget) { - provider.initializeAnimation(); - return CustomPaint( - size: const Size(400, 480), - painter: BadgePaint(grid: provider.getPaintGrid()), - ); - }), ); } } + +// class AnimationBadgeROW extends LeafRenderObjectWidget { +// final AnimationBadgeProvider provider; + +// const AnimationBadgeROW({super.key, required this.provider}); + +// @override +// RenderObject createRenderObject(BuildContext context) { +// final renderObject = BadgeRenderObject(provider: provider); +// provider.addListener(renderObject.onProviderUpdate); +// return renderObject; +// } + +// @override +// void updateRenderObject( +// BuildContext context, covariant BadgeRenderObject renderObject) { +// renderObject.provider = provider; +// } +// } + +// class BadgeRenderObject extends RenderBox with RenderObjectWithChildMixin { +// AnimationBadgeProvider provider; + +// BadgeRenderObject({required this.provider}); + +// @override +// void performLayout() { +// var width = constraints.maxWidth; +// size = constraints.constrain(Size(width, width / 3.2)); +// } + +// @override +// void paint(PaintingContext context, Offset offset) { +// final Canvas canvas = context.canvas; +// BadgePaint(grid: provider.getPaintGrid()).paint(canvas, size); +// } + +// @override +// bool get alwaysNeedsCompositing => true; + +// void onProviderUpdate() { +// markNeedsPaint(); +// } +// } diff --git a/lib/virtualbadge/view/badge_paint.dart b/lib/virtualbadge/view/badge_paint.dart index 0d5227a82..782ab0127 100644 --- a/lib/virtualbadge/view/badge_paint.dart +++ b/lib/virtualbadge/view/badge_paint.dart @@ -1,39 +1,81 @@ import 'dart:math' as math; +import 'package:badgemagic/bademagic_module/utils/badge_utils.dart'; import 'package:flutter/material.dart'; class BadgePaint extends CustomPainter { + BadgeUtils badgeUtils = BadgeUtils(); final List> grid; BadgePaint({required this.grid}); @override void paint(Canvas canvas, Size size) { - double cellWidth = size.width / grid[0].length; - double cellHeight = size.height / grid.length; + // Padding for the rectangle + MapEntry badgeOffsetBackground = + badgeUtils.getBadgeOffsetBackground(size); + double offsetHeightBadgeBackground = badgeOffsetBackground.key; + double offsetWidthBadgeBackground = badgeOffsetBackground.value; + // Size of the rectangle + MapEntry badgeSize = badgeUtils.getBadgeSize( + offsetHeightBadgeBackground, offsetWidthBadgeBackground, size); + double badgeHeight = badgeSize.key; + double badgeWidth = badgeSize.value; + + // Draw the outer rectangle + final Paint rectPaint = Paint() + ..style = PaintingStyle.fill + ..color = Colors.black + ..strokeWidth = 2.0; + + final RRect gridRect = RRect.fromLTRBR( + offsetWidthBadgeBackground, + offsetHeightBadgeBackground, + offsetWidthBadgeBackground + badgeWidth, + offsetHeightBadgeBackground + badgeHeight, + const Radius.circular(10.0), + ); + + canvas.drawRRect(gridRect, rectPaint); + + var cellSize = badgeWidth / grid[0].length; + + MapEntry cellStartCoordinate = + badgeUtils.getCellStartCoordinate(offsetWidthBadgeBackground, + offsetHeightBadgeBackground, badgeWidth, badgeHeight); + double cellStartX = cellStartCoordinate.key; + double cellStartY = cellStartCoordinate.value; + // Draw the cells for (int row = 0; row < grid.length; row++) { for (int col = 0; col < grid[row].length; col++) { + var cellStartRow = cellStartY + row * cellSize; + var cellStartCol = cellStartX + col * (cellSize * 0.93); + final Paint paint = Paint() ..color = grid[row][col] ? Colors.red : Colors.grey.shade900 ..style = PaintingStyle.fill; - final Path path = Path() - ..moveTo(col * cellWidth, row * cellHeight) - ..lineTo(col * cellWidth + cellWidth * 0.4, row * cellHeight) - ..lineTo(col * cellWidth + cellWidth * 0.655, - row * cellHeight + cellHeight) - ..lineTo( - col * cellWidth + cellWidth * 0.25, row * cellHeight + cellHeight) - ..close(); + final Rect cellRect = Rect.fromLTWH( + cellStartCol, + cellStartRow, + cellSize / 2.5, + cellSize, + ); - const double radians = math.pi / 4; + // Apply 45-degree rotation canvas.save(); - canvas.translate((col + 0.5) * cellWidth, (row + 0.5) * cellHeight); - canvas.rotate(radians); - canvas.translate(-(col + 0.5) * cellWidth, -(row + 0.5) * cellHeight); + canvas.translate( + cellRect.left + (cellRect.width / 2), + cellRect.top + (cellRect.height / 2), + ); + canvas.rotate(math.pi / 4); + canvas.translate( + -(cellRect.left + (cellRect.width / 2)), + -(cellRect.top + (cellRect.height / 2)), + ); - canvas.drawPath(path, paint); + canvas.drawRect(cellRect, paint); canvas.restore(); } } diff --git a/lib/virtualbadge/view/draw_badge.dart b/lib/virtualbadge/view/draw_badge.dart index e5cb707e5..811a48c05 100644 --- a/lib/virtualbadge/view/draw_badge.dart +++ b/lib/virtualbadge/view/draw_badge.dart @@ -1,5 +1,6 @@ +import 'package:badgemagic/bademagic_module/utils/badge_utils.dart'; import 'package:badgemagic/providers/draw_badge_provider.dart'; -import 'package:badgemagic/virtualbadge/view/draw_badge_paint.dart'; +import 'package:badgemagic/virtualbadge/view/badge_paint.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -13,6 +14,7 @@ class BMBadge extends StatefulWidget { } class _BMBadgeState extends State { + BadgeUtils badgeUtils = BadgeUtils(); var drawProvider = DrawBadgeProvider(); @override @@ -32,29 +34,124 @@ class _BMBadgeState extends State { void _handlePanUpdate(DragUpdateDetails details) { RenderBox renderBox = context.findRenderObject() as RenderBox; Offset localPosition = renderBox.globalToLocal(details.globalPosition); - double cellWidth = renderBox.size.width / cols; - double cellHeight = renderBox.size.height / rows; - int col = (localPosition.dx / cellWidth).clamp(0, cols - 1).toInt(); - int row = (localPosition.dy / cellHeight).clamp(0, rows - 1).toInt(); + MapEntry badgeOffsetBackground = + badgeUtils.getBadgeOffsetBackground(renderBox.size); + double offsetHeightBadgeBackground = badgeOffsetBackground.key; + double offsetWidthBadgeBackground = badgeOffsetBackground.value; - setState(() { + MapEntry badgeSize = badgeUtils.getBadgeSize( + offsetHeightBadgeBackground, + offsetWidthBadgeBackground, + renderBox.size); + double badgeHeight = badgeSize.key; + double badgeWidth = badgeSize.value; + + var cellSize = badgeWidth / cols; + + MapEntry cellStartCoordinate = + badgeUtils.getCellStartCoordinate(offsetWidthBadgeBackground, + offsetHeightBadgeBackground, badgeWidth, badgeHeight); + double cellStartX = cellStartCoordinate.key; + double cellStartY = cellStartCoordinate.value; + + double cellEnd = cellStartX + (cellSize * cols); + double cellEndY = cellStartY + ((cellSize * 0.93) * rows); + + if (localPosition.dx > cellStartX && + localPosition.dx > cellStartY && + localPosition.dx < cellEnd && + localPosition.dy < cellEndY * 1.1) { + int col = ((localPosition.dx - cellStartX) / (cellSize * 0.93)) + .floor() + .clamp(0, 43); + int row = + ((localPosition.dy - cellStartY) / cellSize).floor().clamp(0, 10); drawProvider.setDrawViewGrid(row, col); + } + + setState(() { + // drawProvider.setDrawViewGrid(row, col); }); } @override Widget build(BuildContext context) { + var width = MediaQuery.of(context).size.width; + Size size = Size(width, width / 3.2); return ChangeNotifierProvider( create: (context) => drawProvider, child: GestureDetector( onPanUpdate: _handlePanUpdate, - child: Consumer( - builder: (context, value, child) => CustomPaint( - size: const Size(400, 480), - painter: DrawBadgePaint(grid: value.getDrawViewGrid()), + child: AspectRatio( + aspectRatio: 3.2, + child: Consumer( + builder: (context, value, child) => CustomPaint( + painter: BadgePaint(grid: value.getDrawViewGrid()), + size: size), ), )), ); } } + +// class AnimationBadgeROW extends LeafRenderObjectWidget { +// final DrawBadgeProvider provider; + +// const AnimationBadgeROW({super.key, required this.provider}); + +// @override +// RenderObject createRenderObject(BuildContext context) { +// final renderObject = BadgeRenderObject(provider: provider); +// provider.addListener(renderObject.onProviderUpdate); +// return renderObject; +// } + +// @override +// void updateRenderObject( +// BuildContext context, covariant BadgeRenderObject renderObject) { +// renderObject.provider = provider; +// } +// } + +// class BadgeRenderObject extends RenderBox with RenderObjectWithChildMixin { +// DrawBadgeProvider provider; + +// BadgeRenderObject({required this.provider}); + +// @override +// void performLayout() { +// var width = constraints.maxWidth; +// var height = constraints.maxHeight; + +// // Maintain aspect ratio but ensure it fits within the available height +// var desiredHeight = width / 3.2; +// if (desiredHeight > height) { +// desiredHeight = height; +// } + +// size = constraints.constrain(Size(width, desiredHeight)); +// } + +// @override +// void paint(PaintingContext context, Offset offset) { +// final Canvas canvas = context.canvas; +// BadgePaint(grid: provider.getDrawViewGrid()).paint(canvas, size); +// } + +// @override +// bool get alwaysNeedsCompositing => true; + +// void onProviderUpdate() { +// markNeedsPaint(); +// } + +// @override +// bool hitTest(BoxHitTestResult result, {required Offset position}) { +// if (size.contains(position)) { +// result.add(BoxHitTestEntry(this, position)); +// return true; +// } +// return false; +// } +// } diff --git a/lib/virtualbadge/view/draw_badge_paint.dart b/lib/virtualbadge/view/draw_badge_paint.dart deleted file mode 100644 index 8b828b5e5..000000000 --- a/lib/virtualbadge/view/draw_badge_paint.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'dart:math' as math; - -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class DrawBadgePaint extends CustomPainter { - final List> grid; - - const DrawBadgePaint({required this.grid}); - - @override - void paint(Canvas canvas, Size size) { - double cellWidth = size.width / grid[0].length; - double cellHeight = size.height / grid.length; - - double pathOffsetX1 = 0.15.w; - double pathOffsetX2 = 0.3.w; - double pathOffsetX3 = 0.15.w; - - for (int row = 0; row < grid.length; row++) { - for (int col = 0; col < grid[row].length; col++) { - final Paint paint = Paint() - ..color = grid[row][col] ? Colors.red : Colors.grey.shade900 - ..style = PaintingStyle.fill; - - final Path path = Path() - ..moveTo(col * cellWidth, row * cellHeight) - ..lineTo(col * cellWidth + cellWidth * pathOffsetX1, row * cellHeight) - ..lineTo(col * cellWidth + cellWidth * pathOffsetX2, - row * cellHeight + cellHeight) - ..lineTo(col * cellWidth + cellWidth * pathOffsetX3, - row * cellHeight + cellHeight) - ..close(); - - const double radians = math.pi / 3; - canvas.save(); - canvas.translate((col + 0.5) * cellWidth, (row + 0.5) * cellHeight); - canvas.rotate(radians); - canvas.translate(-(col + 0.5) * cellWidth, -(row + 0.5) * cellHeight); - - canvas.drawPath(path, paint); - canvas.restore(); - } - } - } - - @override - bool shouldRepaint(covariant CustomPainter oldDelegate) { - return true; - } -}