@@ -5,17 +5,64 @@ import 'dart:math' as math;
55
66import 'package:provider/provider.dart' ;
77
8- // The main NodePicker widget as per the design
9- class NodePicker extends StatelessWidget {
8+ // The main NodePicker widget, now stateful
9+ class NodePicker extends StatefulWidget {
1010 const NodePicker ({super .key});
1111
12+ @override
13+ State <NodePicker > createState () => _NodePickerState ();
14+ }
15+
16+ class _NodePickerState extends State <NodePicker > {
17+ late final TextEditingController _searchController;
18+ late final List <Map <String , dynamic >> _allShapes;
19+ List <Map <String , dynamic >> _filteredShapes = [];
20+
21+ @override
22+ void initState () {
23+ super .initState ();
24+ _searchController = TextEditingController ();
25+
26+ // Define all available shapes
27+ _allShapes = [
28+ {'name' : 'Square' , 'drawMode' : DrawMode .square, 'shapeType' : ShapeType .square},
29+ {'name' : 'Diamond' , 'drawMode' : DrawMode .diamond, 'shapeType' : ShapeType .diamond},
30+ {'name' : 'Rounded Square' , 'drawMode' : DrawMode .roundedSquare, 'shapeType' : ShapeType .roundedSquare},
31+ {'name' : 'Parallelogram' , 'drawMode' : DrawMode .parallelogram, 'shapeType' : ShapeType .parallelogram},
32+ {'name' : 'Cylinder' , 'drawMode' : DrawMode .cylinder, 'shapeType' : ShapeType .cylinder},
33+ {'name' : 'Circle' , 'drawMode' : DrawMode .circle, 'shapeType' : ShapeType .circle},
34+ {'name' : 'Triangle' , 'drawMode' : DrawMode .triangle, 'shapeType' : ShapeType .triangle},
35+ {'name' : 'Inverted Triangle' , 'drawMode' : DrawMode .invertedTriangle, 'shapeType' : ShapeType .invertedTriangle},
36+ ];
37+
38+ _filteredShapes = _allShapes;
39+
40+ _searchController.addListener (_filterShapes);
41+ }
42+
43+ void _filterShapes () {
44+ final query = _searchController.text.toLowerCase ();
45+ setState (() {
46+ _filteredShapes = _allShapes.where ((shape) {
47+ final shapeName = shape['name' ].toString ().toLowerCase ();
48+ return shapeName.contains (query);
49+ }).toList ();
50+ });
51+ }
52+
53+ @override
54+ void dispose () {
55+ _searchController.removeListener (_filterShapes);
56+ _searchController.dispose ();
57+ super .dispose ();
58+ }
59+
1260 @override
1361 Widget build (BuildContext context) {
14- // Using a container to create the card-like appearance
1562 return Consumer <WorkspaceProvider >(
1663 builder: (context, provider, child) {
1764 return Container (
18- width: 340 , // Fixed width as it appears in the image
65+ width: 340 ,
1966 padding: const EdgeInsets .all (24.0 ),
2067 decoration: BoxDecoration (
2168 color: Colors .white,
@@ -29,11 +76,9 @@ class NodePicker extends StatelessWidget {
2976 ],
3077 ),
3178 child: Column (
32- mainAxisSize:
33- MainAxisSize .min, // To make the column wrap its content
79+ mainAxisSize: MainAxisSize .min,
3480 crossAxisAlignment: CrossAxisAlignment .start,
3581 children: [
36- // Header section with Title and Close button
3782 Row (
3883 mainAxisAlignment: MainAxisAlignment .spaceBetween,
3984 children: [
@@ -45,15 +90,13 @@ class NodePicker extends StatelessWidget {
4590 color: Color (0xFF111827 ),
4691 ),
4792 ),
48- // The close button inside the picker itself
4993 IconButton (
5094 icon: const Icon (
5195 Icons .close,
5296 color: Color (0xFF111827 ),
5397 size: 28 ,
5498 ),
5599 onPressed: () {
56- // Closes the dialog
57100 Navigator .of (context).pop ();
58101 },
59102 ),
@@ -62,6 +105,7 @@ class NodePicker extends StatelessWidget {
62105 const SizedBox (height: 20 ),
63106 // Search bar
64107 TextField (
108+ controller: _searchController,
65109 decoration: InputDecoration (
66110 hintText: 'Search for a shape' ,
67111 hintStyle: const TextStyle (color: Color (0xFF9CA3AF )),
@@ -91,52 +135,25 @@ class NodePicker extends StatelessWidget {
91135 ),
92136 const SizedBox (height: 24 ),
93137 // Grid of shapes
94- GridView .count (
95- crossAxisCount: 4 ,
96- shrinkWrap:
97- true , // Important to make GridView work inside a Column
98- physics:
99- const NeverScrollableScrollPhysics (), // Disable scrolling in the grid
100- mainAxisSpacing: 16 ,
101- crossAxisSpacing: 16 ,
102- children: [
103- GestureDetector (
104- onTap: () => provider.changeDrawMode (DrawMode .square),
105- child: ShapeWidget (shapeType: ShapeType .square),
106- ),
107- GestureDetector (
108- onTap: () => provider.changeDrawMode (DrawMode .diamond),
109- child: ShapeWidget (shapeType: ShapeType .diamond),
110- ),
111- GestureDetector (
112- onTap:
113- () => provider.changeDrawMode (DrawMode .roundedSquare),
114- child: ShapeWidget (shapeType: ShapeType .roundedSquare),
115- ),
116- GestureDetector (
117- onTap:
118- () => provider.changeDrawMode (DrawMode .parallelogram),
119- child: ShapeWidget (shapeType: ShapeType .parallelogram),
120- ),
121- GestureDetector (
122- onTap: () => provider.changeDrawMode (DrawMode .cylinder),
123- child: ShapeWidget (shapeType: ShapeType .cylinder),
124- ),
125- GestureDetector (
126- onTap: () => provider.changeDrawMode (DrawMode .circle),
127- child: ShapeWidget (shapeType: ShapeType .circle),
128- ),
129- GestureDetector (
130- onTap: () => provider.changeDrawMode (DrawMode .triangle),
131- child: ShapeWidget (shapeType: ShapeType .triangle),
132- ),
133- GestureDetector (
134- onTap:
135- () =>
136- provider.changeDrawMode (DrawMode .invertedTriangle),
137- child: ShapeWidget (shapeType: ShapeType .invertedTriangle),
138- ),
139- ],
138+ GridView .builder (
139+ gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount (
140+ crossAxisCount: 4 ,
141+ mainAxisSpacing: 16 ,
142+ crossAxisSpacing: 16 ,
143+ ),
144+ itemCount: _filteredShapes.length,
145+ shrinkWrap: true ,
146+ physics: const NeverScrollableScrollPhysics (),
147+ itemBuilder: (context, index) {
148+ final shape = _filteredShapes[index];
149+ return GestureDetector (
150+ onTap: () {
151+ provider.changeDrawMode (shape['drawMode' ]);
152+ Navigator .of (context).pop (); // Close picker on selection
153+ },
154+ child: ShapeWidget (shapeType: shape['shapeType' ]),
155+ );
156+ },
140157 ),
141158 ],
142159 ),
@@ -158,7 +175,7 @@ class ShapeWidget extends StatelessWidget {
158175 width: 60 ,
159176 height: 60 ,
160177 decoration: BoxDecoration (
161- color: Colors .transparent, // transparent background
178+ color: Colors .transparent,
162179 borderRadius: BorderRadius .circular (8.0 ),
163180 ),
164181 child: CustomPaint (painter: ShapePainter (shapeType: shapeType)),
@@ -178,7 +195,7 @@ class ShapePainter extends CustomPainter {
178195 Paint ()
179196 ..color =
180197 Colors
181- .black // A nice purple-blue color
198+ .black
182199 ..style = PaintingStyle .stroke
183200 ..strokeWidth = 1.0 ;
184201
@@ -239,7 +256,7 @@ class ShapePainter extends CustomPainter {
239256 );
240257 canvas.drawLine (rect.topLeft, rect.bottomLeft, paint);
241258 canvas.drawLine (rect.topRight, rect.bottomRight, paint);
242- return ; // Return early as we are drawing multiple parts
259+ return ;
243260 case ShapeType .circle:
244261 path.addOval (Rect .fromLTWH (w * 0.1 , h * 0.1 , w * 0.8 , h * 0.8 ));
245262 break ;
@@ -263,4 +280,4 @@ class ShapePainter extends CustomPainter {
263280 bool shouldRepaint (covariant CustomPainter oldDelegate) {
264281 return false ;
265282 }
266- }
283+ }
0 commit comments