I am working on a shape management application. I need to add the selection box for selected shape if there is any shape selected while selecting another shape the previous selected shape needs to be deselected. I am storing the Shape class instance in a global variable Shape? selectedShape; how to call this setState() using the stored instance.
class Layer {
final LayerListData layerDetails;
final List<ShapeData> shapes;
Layer({required this.layerDetails, required this.shapes});
}
class LayerStack extends StatelessWidget {
final List<Layer> layers;
final int selectedLayerIndex;
final Function(int) onLayerTap;
const LayerStack({
Key? key,
required this.layers,
required this.selectedLayerIndex,
required this.onLayerTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
children: [
for (int i = 0; i < layers.length; i++)
LayerWidget(
layer: layers[i],
),
],
);
}
}
class LayerWidget extends StatefulWidget {
final Layer layer;
const LayerWidget({
Key? key,
required this.layer,
}) : super(key: key);
@override
State<LayerWidget> createState() => _LayerWidgetState();
}
class _LayerWidgetState extends State<LayerWidget> {
@override
Widget build(BuildContext context) {
return Stack(
children: [
for (final shapeData in widget.layer.shapes)
Shape(
shapeData: shapeData,
isSelected: true,
onTap: (value) {},
),
],
);
}
}
class ShapeData {
ShapeListData shapeData;
ShapeTextData shapeTextData;
ShapeArrangeData shapeArrangeData;
ShapeStyleData shapeStyleData;
ShapeData(
{required this.shapeData,
required this.shapeStyleData,
required this.shapeTextData,
required this.shapeArrangeData});
}
class Shape extends StatefulWidget {
final ShapeData shapeData;
bool isSelected;
final Function(bool) onTap;
final VoidCallback? updateStateCallback;
Shape(
{Key? key,
required this.shapeData,
this.isSelected = false,
required this.onTap,
this.updateStateCallback})
: super(key: key);
@override
State<Shape> createState() => _ShapeState();
}
class _ShapeState extends State<Shape> {
@override
void initState() {
super.initState();
widget.isSelected = false;
}
@override
void dispose() {
super.dispose();
widget.isSelected = false;
}
@override
Widget build(BuildContext context) {
return Positioned(
left:
double.tryParse(widget.shapeData.shapeArrangeData.positionX ?? '0.0'),
top:
double.tryParse(widget.shapeData.shapeArrangeData.positionY ?? '0.0'),
child: GestureDetector(
onTap: () {
setState(() {
// Deselect the previously selected shape
if (selectedShape != null && selectedShape != widget) {
selectedShape!.isSelected = false;
selectedShape!.updateStateCallback?.call();
}
// Select the newly tapped shape
selectedShape = widget;
widget.isSelected = true;
widget.updateStateCallback?.call();
});
},
child: Stack(
children: [
// CustomPaint for drawing the shape
CustomPaint(
painter: ShapeCustomPainter(shapeData: widget.shapeData),
size: const Size(45, 50),
),
// selection indicator if the shape is selected
if (widget.isSelected)
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue, width: 2.0),
),
),
],
),
),
);
}
}
class ShapeCustomPainter extends CustomPainter {
ShapeData shapeData;
ShapeCustomPainter({required this.shapeData});
@override
void paint(Canvas canvas, Size size) {
final Paint fillPaint = Paint()
..color = Color(int.parse(
shapeData.shapeStyleData.lineColor?.replaceFirst('#', '0xFF') ??
'0xFF000000'))
..strokeWidth = (shapeData.shapeStyleData.strokeSize)?.toDouble() ?? 1.0
..style = PaintingStyle.stroke;
final Paint strokePaint = Paint()
..color = Color(int.parse(
shapeData.shapeStyleData.lineColor?.replaceFirst('#', '0xFF') ??
'0xFFFFFFFF'))
..style = PaintingStyle.fill;
final Path shapePath =
ShapePathGenerator(shapeString: shapeData.shapeData.shapeString ?? '')
.getPath();
canvas.drawPath(shapePath, fillPaint);
canvas.drawPath(shapePath, strokePaint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
} ```