Feat: Ajout d'un switch pour masquer ou afficher le slider d'espacement de la cible
This commit is contained in:
@@ -4,7 +4,6 @@
|
|||||||
/// Les anneaux sont répartis proportionnellement.
|
/// Les anneaux sont répartis proportionnellement.
|
||||||
library;
|
library;
|
||||||
|
|
||||||
import 'dart:math' as math;
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../../../core/theme/app_theme.dart';
|
import '../../../core/theme/app_theme.dart';
|
||||||
import '../../../data/models/target_type.dart';
|
import '../../../data/models/target_type.dart';
|
||||||
@@ -18,13 +17,13 @@ class TargetCalibration extends StatefulWidget {
|
|||||||
final TargetType targetType;
|
final TargetType targetType;
|
||||||
final List<double>? initialRingRadii;
|
final List<double>? initialRingRadii;
|
||||||
final Function(
|
final Function(
|
||||||
double centerX,
|
double centerX,
|
||||||
double centerY,
|
double centerY,
|
||||||
double innerRadius,
|
double innerRadius,
|
||||||
double radius,
|
double radius,
|
||||||
int ringCount, {
|
int ringCount, {
|
||||||
List<double>? ringRadii,
|
List<double>? ringRadii,
|
||||||
})
|
})
|
||||||
onCalibrationChanged;
|
onCalibrationChanged;
|
||||||
|
|
||||||
const TargetCalibration({
|
const TargetCalibration({
|
||||||
@@ -55,6 +54,9 @@ class TargetCalibrationState extends State<TargetCalibration> {
|
|||||||
bool _isDraggingRadius = false;
|
bool _isDraggingRadius = false;
|
||||||
bool _isDraggingInnerRadius = false;
|
bool _isDraggingInnerRadius = false;
|
||||||
|
|
||||||
|
// Contrôle de l'affichage du scroll d'espacement (désactivé par défaut)
|
||||||
|
bool _showEspacement = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -138,13 +140,13 @@ class TargetCalibrationState extends State<TargetCalibration> {
|
|||||||
ringRadii: _ringRadii,
|
ringRadii: _ringRadii,
|
||||||
targetType: widget.targetType,
|
targetType: widget.targetType,
|
||||||
isDraggingCenter: _isDraggingCenter,
|
isDraggingCenter: _isDraggingCenter,
|
||||||
isDraggingRadius: false, // Plus de drag direct du rayon
|
isDraggingRadius: false,
|
||||||
isDraggingInnerRadius: false,
|
isDraggingInnerRadius: false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Slider pour le rayon (agrandissement)
|
// Panneau de configuration des Sliders en haut
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 10,
|
top: 10,
|
||||||
left: 40,
|
left: 40,
|
||||||
@@ -152,6 +154,38 @@ class TargetCalibrationState extends State<TargetCalibration> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
// Ligne d'activation pour afficher ou masquer l'espacement
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(bottom: 8), // CORRECTION de la syntaxe de marge
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.black54,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Options d\'espacement avancées',
|
||||||
|
style: TextStyle(color: Colors.white70, fontSize: 11, fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 28,
|
||||||
|
child: Switch(
|
||||||
|
value: _showEspacement,
|
||||||
|
activeThumbColor: const Color(0xFF00FF00), // CORRECTION du paramètre déprécié
|
||||||
|
onChanged: (bool value) {
|
||||||
|
setState(() {
|
||||||
|
_showEspacement = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Slider pour la taille (toujours visible)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@@ -171,7 +205,6 @@ class TargetCalibrationState extends State<TargetCalibration> {
|
|||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_radius = value;
|
_radius = value;
|
||||||
// On force le recalcul car on change la taille
|
|
||||||
_initRingRadii(forceRecalculate: true);
|
_initRingRadii(forceRecalculate: true);
|
||||||
});
|
});
|
||||||
_notifyChange();
|
_notifyChange();
|
||||||
@@ -182,37 +215,40 @@ class TargetCalibrationState extends State<TargetCalibration> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
|
||||||
Container(
|
// Affichage conditionnel du slider d'espacement orange
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
if (_showEspacement) ...[
|
||||||
decoration: BoxDecoration(
|
const SizedBox(height: 8),
|
||||||
color: Colors.black54,
|
Container(
|
||||||
borderRadius: BorderRadius.circular(20),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||||
),
|
decoration: BoxDecoration(
|
||||||
child: Row(
|
color: Colors.black54,
|
||||||
children: [
|
borderRadius: BorderRadius.circular(20),
|
||||||
const Text('Espacement ', style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold)),
|
),
|
||||||
const Icon(Icons.compress, color: Colors.white, size: 16),
|
child: Row(
|
||||||
Expanded(
|
children: [
|
||||||
child: Slider(
|
const Text('Espacement ', style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold)),
|
||||||
value: (_innerRadius / _radius).clamp(0.01, 0.9),
|
const Icon(Icons.compress, color: Colors.white, size: 16),
|
||||||
min: 0.01,
|
Expanded(
|
||||||
max: 0.9,
|
child: Slider(
|
||||||
activeColor: Colors.orange,
|
value: (_innerRadius / _radius).clamp(0.01, 0.9),
|
||||||
onChanged: (value) {
|
min: 0.01,
|
||||||
setState(() {
|
max: 0.9,
|
||||||
// On ajuste l'innerRadius comme un ratio du radius global
|
activeColor: Colors.orange,
|
||||||
_innerRadius = _radius * value;
|
onChanged: (value) {
|
||||||
_initRingRadii(forceRecalculate: true);
|
setState(() {
|
||||||
});
|
_innerRadius = _radius * value;
|
||||||
_notifyChange();
|
_initRingRadii(forceRecalculate: true);
|
||||||
},
|
});
|
||||||
|
_notifyChange();
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
const Icon(Icons.expand, color: Colors.white, size: 16),
|
||||||
const Icon(Icons.expand, color: Colors.white, size: 16),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -236,25 +272,25 @@ class TargetCalibrationState extends State<TargetCalibration> {
|
|||||||
children: [
|
children: [
|
||||||
_buildDirectionButton(
|
_buildDirectionButton(
|
||||||
Icons.keyboard_arrow_up,
|
Icons.keyboard_arrow_up,
|
||||||
() => _moveCenterByPixels(0, -1, size),
|
() => _moveCenterByPixels(0, -1, size),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
_buildDirectionButton(
|
_buildDirectionButton(
|
||||||
Icons.keyboard_arrow_left,
|
Icons.keyboard_arrow_left,
|
||||||
() => _moveCenterByPixels(-1, 0, size),
|
() => _moveCenterByPixels(-1, 0, size),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 40),
|
const SizedBox(width: 40),
|
||||||
_buildDirectionButton(
|
_buildDirectionButton(
|
||||||
Icons.keyboard_arrow_right,
|
Icons.keyboard_arrow_right,
|
||||||
() => _moveCenterByPixels(1, 0, size),
|
() => _moveCenterByPixels(1, 0, size),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
_buildDirectionButton(
|
_buildDirectionButton(
|
||||||
Icons.keyboard_arrow_down,
|
Icons.keyboard_arrow_down,
|
||||||
() => _moveCenterByPixels(0, 1, size),
|
() => _moveCenterByPixels(0, 1, size),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -301,7 +337,7 @@ class TargetCalibrationState extends State<TargetCalibration> {
|
|||||||
final tapY = details.localPosition.dy / size.height;
|
final tapY = details.localPosition.dy / size.height;
|
||||||
|
|
||||||
final distToCenter = _distance(tapX, tapY, _centerX, _centerY);
|
final distToCenter = _distance(tapX, tapY, _centerX, _centerY);
|
||||||
|
|
||||||
if (distToCenter < 0.05 || distToCenter < _radius + 0.02) {
|
if (distToCenter < 0.05 || distToCenter < _radius + 0.02) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isDraggingCenter = true;
|
_isDraggingCenter = true;
|
||||||
@@ -312,11 +348,9 @@ class TargetCalibrationState extends State<TargetCalibration> {
|
|||||||
void _onPanUpdate(DragUpdateDetails details, Size size) {
|
void _onPanUpdate(DragUpdateDetails details, Size size) {
|
||||||
final deltaX = details.delta.dx / size.width;
|
final deltaX = details.delta.dx / size.width;
|
||||||
final deltaY = details.delta.dy / size.height;
|
final deltaY = details.delta.dy / size.height;
|
||||||
final minDim = math.min(size.width, size.height);
|
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
if (_isDraggingCenter) {
|
if (_isDraggingCenter) {
|
||||||
// Move center
|
|
||||||
_centerX = _centerX + deltaX;
|
_centerX = _centerX + deltaX;
|
||||||
_centerY = _centerY + deltaY;
|
_centerY = _centerY + deltaY;
|
||||||
}
|
}
|
||||||
@@ -370,7 +404,6 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
final centerPx = Offset(centerX * size.width, centerY * size.height);
|
final centerPx = Offset(centerX * size.width, centerY * size.height);
|
||||||
final minDim = size.width < size.height ? size.width : size.height;
|
final minDim = size.width < size.height ? size.width : size.height;
|
||||||
final baseRadiusPx = radius * minDim;
|
final baseRadiusPx = radius * minDim;
|
||||||
final innerRadiusPx = innerRadius * minDim;
|
|
||||||
|
|
||||||
if (targetType == TargetType.concentric) {
|
if (targetType == TargetType.concentric) {
|
||||||
_drawConcentricZones(canvas, size, centerPx, baseRadiusPx);
|
_drawConcentricZones(canvas, size, centerPx, baseRadiusPx);
|
||||||
@@ -378,7 +411,6 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
_drawSilhouetteZones(canvas, size, centerPx, baseRadiusPx);
|
_drawSilhouetteZones(canvas, size, centerPx, baseRadiusPx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fullscreen crosshairs when dragging center
|
|
||||||
if (isDraggingCenter) {
|
if (isDraggingCenter) {
|
||||||
final crosshairLinePaint = Paint()
|
final crosshairLinePaint = Paint()
|
||||||
..color = Colors.red.withValues(alpha: 0.5)
|
..color = Colors.red.withValues(alpha: 0.5)
|
||||||
@@ -395,20 +427,16 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw center handle
|
|
||||||
_drawCenterHandle(canvas, centerPx);
|
_drawCenterHandle(canvas, centerPx);
|
||||||
|
|
||||||
// Draw instructions
|
|
||||||
_drawInstructions(canvas, size);
|
_drawInstructions(canvas, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _drawConcentricZones(
|
void _drawConcentricZones(
|
||||||
Canvas canvas,
|
Canvas canvas,
|
||||||
Size size,
|
Size size,
|
||||||
Offset center,
|
Offset center,
|
||||||
double baseRadius,
|
double baseRadius,
|
||||||
) {
|
) {
|
||||||
// Generate colors for zones
|
|
||||||
List<Color> zoneColors = [];
|
List<Color> zoneColors = [];
|
||||||
for (int i = 0; i < ringCount; i++) {
|
for (int i = 0; i < ringCount; i++) {
|
||||||
final ratio = i / ringCount;
|
final ratio = i / ringCount;
|
||||||
@@ -431,7 +459,6 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
..strokeWidth = 1
|
..strokeWidth = 1
|
||||||
..color = Colors.red.withValues(alpha: 0.8);
|
..color = Colors.red.withValues(alpha: 0.8);
|
||||||
|
|
||||||
// Draw from outside to inside
|
|
||||||
for (int i = ringCount - 1; i >= 0; i--) {
|
for (int i = ringCount - 1; i >= 0; i--) {
|
||||||
final ringRadius = ringRadii.length > i
|
final ringRadius = ringRadii.length > i
|
||||||
? ringRadii[i]
|
? ringRadii[i]
|
||||||
@@ -443,7 +470,6 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
canvas.drawCircle(center, zoneRadius, strokePaint);
|
canvas.drawCircle(center, zoneRadius, strokePaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw zone labels (only if within visible area)
|
|
||||||
final textPainter = TextPainter(textDirection: TextDirection.ltr);
|
final textPainter = TextPainter(textDirection: TextDirection.ltr);
|
||||||
|
|
||||||
for (int i = 0; i < ringCount; i++) {
|
for (int i = 0; i < ringCount; i++) {
|
||||||
@@ -455,10 +481,7 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
: 0.0;
|
: 0.0;
|
||||||
final zoneRadius = baseRadius * (ringRadius + prevRingRadius) / 2;
|
final zoneRadius = baseRadius * (ringRadius + prevRingRadius) / 2;
|
||||||
|
|
||||||
// Score: center = 10, decrement by 1 for each ring
|
|
||||||
final score = 10 - i;
|
final score = 10 - i;
|
||||||
|
|
||||||
// Only draw label if it's within the visible area
|
|
||||||
final labelX = center.dx + zoneRadius;
|
final labelX = center.dx + zoneRadius;
|
||||||
if (labelX < 0 || labelX > size.width) continue;
|
if (labelX < 0 || labelX > size.width) continue;
|
||||||
|
|
||||||
@@ -473,7 +496,6 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
);
|
);
|
||||||
textPainter.layout();
|
textPainter.layout();
|
||||||
|
|
||||||
// Draw label on the right side of each zone
|
|
||||||
final labelY = center.dy - textPainter.height / 2;
|
final labelY = center.dy - textPainter.height / 2;
|
||||||
if (labelY >= 0 && labelY <= size.height) {
|
if (labelY >= 0 && labelY <= size.height) {
|
||||||
textPainter.paint(
|
textPainter.paint(
|
||||||
@@ -485,17 +507,15 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _drawSilhouetteZones(
|
void _drawSilhouetteZones(
|
||||||
Canvas canvas,
|
Canvas canvas,
|
||||||
Size size,
|
Size size,
|
||||||
Offset center,
|
Offset center,
|
||||||
double radius,
|
double radius,
|
||||||
) {
|
) {
|
||||||
// Simplified silhouette zones
|
|
||||||
final paint = Paint()
|
final paint = Paint()
|
||||||
..style = PaintingStyle.stroke
|
..style = PaintingStyle.stroke
|
||||||
..strokeWidth = 2;
|
..strokeWidth = 2;
|
||||||
|
|
||||||
// Draw silhouette outline (simplified as rectangle for now)
|
|
||||||
final silhouetteWidth = radius * 0.8;
|
final silhouetteWidth = radius * 0.8;
|
||||||
final silhouetteHeight = radius * 2;
|
final silhouetteHeight = radius * 2;
|
||||||
|
|
||||||
@@ -511,43 +531,24 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _drawCenterHandle(Canvas canvas, Offset center) {
|
void _drawCenterHandle(Canvas canvas, Offset center) {
|
||||||
// Outer circle
|
|
||||||
final outerPaint = Paint()
|
final outerPaint = Paint()
|
||||||
..color = isDraggingCenter ? Colors.redAccent : Colors.red
|
..color = isDraggingCenter ? Colors.redAccent : Colors.red
|
||||||
..style = PaintingStyle.stroke
|
..style = PaintingStyle.stroke
|
||||||
..strokeWidth = 3;
|
..strokeWidth = 3;
|
||||||
canvas.drawCircle(center, 15, outerPaint);
|
canvas.drawCircle(center, 15, outerPaint);
|
||||||
|
|
||||||
// Inner dot
|
|
||||||
final innerPaint = Paint()
|
final innerPaint = Paint()
|
||||||
..color = isDraggingCenter ? Colors.redAccent : Colors.red
|
..color = isDraggingCenter ? Colors.redAccent : Colors.red
|
||||||
..style = PaintingStyle.fill;
|
..style = PaintingStyle.fill;
|
||||||
canvas.drawCircle(center, 5, innerPaint);
|
canvas.drawCircle(center, 5, innerPaint);
|
||||||
|
|
||||||
// Crosshair
|
|
||||||
final crossPaint = Paint()
|
final crossPaint = Paint()
|
||||||
..color = isDraggingCenter ? Colors.redAccent : Colors.red
|
..color = isDraggingCenter ? Colors.redAccent : Colors.red
|
||||||
..strokeWidth = 2;
|
..strokeWidth = 2;
|
||||||
canvas.drawLine(
|
canvas.drawLine(Offset(center.dx - 20, center.dy), Offset(center.dx - 8, center.dy), crossPaint);
|
||||||
Offset(center.dx - 20, center.dy),
|
canvas.drawLine(Offset(center.dx + 8, center.dy), Offset(center.dx + 20, center.dy), crossPaint);
|
||||||
Offset(center.dx - 8, center.dy),
|
canvas.drawLine(Offset(center.dx, center.dy - 20), Offset(center.dx, center.dy - 8), crossPaint);
|
||||||
crossPaint,
|
canvas.drawLine(Offset(center.dx, center.dy + 8), Offset(center.dx, center.dy + 20), crossPaint);
|
||||||
);
|
|
||||||
canvas.drawLine(
|
|
||||||
Offset(center.dx + 8, center.dy),
|
|
||||||
Offset(center.dx + 20, center.dy),
|
|
||||||
crossPaint,
|
|
||||||
);
|
|
||||||
canvas.drawLine(
|
|
||||||
Offset(center.dx, center.dy - 20),
|
|
||||||
Offset(center.dx, center.dy - 8),
|
|
||||||
crossPaint,
|
|
||||||
);
|
|
||||||
canvas.drawLine(
|
|
||||||
Offset(center.dx, center.dy + 8),
|
|
||||||
Offset(center.dx, center.dy + 20),
|
|
||||||
crossPaint,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _drawInstructions(Canvas canvas, Size size) {
|
void _drawInstructions(Canvas canvas, Size size) {
|
||||||
@@ -584,4 +585,4 @@ class _CalibrationPainter extends CustomPainter {
|
|||||||
isDraggingInnerRadius != oldDelegate.isDraggingInnerRadius ||
|
isDraggingInnerRadius != oldDelegate.isDraggingInnerRadius ||
|
||||||
ringRadii != oldDelegate.ringRadii;
|
ringRadii != oldDelegate.ringRadii;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user