11// lib/features/workspace/pages/workspace_desktop.dart (Fully Modified)
2-
3- import 'package:cookethflow/core/helpers/responsive_layout.helper.dart' as rh;
42import 'package:cookethflow/core/providers/supabase_provider.dart' ;
3+ import 'package:cookethflow/core/utils/enums.dart' ;
54import 'package:cookethflow/features/workspace/pages/canvas_page.dart' ;
65import 'package:cookethflow/features/workspace/providers/canvas_provider.dart' ;
76import 'package:cookethflow/features/workspace/providers/workspace_provider.dart' ;
@@ -10,85 +9,177 @@ import 'package:cookethflow/features/workspace/widgets/node_editing_toolbox.dart
109import 'package:cookethflow/features/workspace/widgets/toolbar.dart' ;
1110import 'package:cookethflow/features/workspace/widgets/undo_redo_button.dart' ;
1211import 'package:cookethflow/features/workspace/widgets/workspace_drawer.dart' ;
12+ import 'package:cookethflow/features/workspace/widgets/workspace_shortcuts.dart' ; // shortcut file
1313import 'package:cookethflow/features/workspace/widgets/zoom_control_button.dart' ;
1414import 'package:flutter/material.dart' ;
1515import 'package:provider/provider.dart' ;
1616import 'package:flutter_screenutil/flutter_screenutil.dart' ;
1717import 'package:cookethflow/features/workspace/widgets/object_text_editor.dart' ;
1818import 'package:vector_math/vector_math_64.dart' as vector_math;
1919
20- class WorkspaceDesktop extends StatelessWidget {
20+ class WorkspaceDesktop extends StatefulWidget {
2121 const WorkspaceDesktop ({super .key});
2222
2323 @override
24- Widget build (BuildContext context) {
25- bool isDesktop =
26- rh.ResponsiveLayoutHelper .getDeviceType (context) ==
27- rh.DeviceType .desktop;
28-
29- return Consumer2 <WorkspaceProvider ,SupabaseService >(builder: (context, provider,suprovider, child) {
30- return Scaffold (
31- backgroundColor: provider.currentWorkspaceColor,
32- body: Padding (
33- padding: EdgeInsets .symmetric (horizontal: 40. w, vertical: 40. h),
34- child: Stack (
35- clipBehavior: Clip .none,
36- children: [
37- const CanvasPage (),
38-
39- const WorkspaceDrawer (),
40- SizedBox (width: 20. w),
41- Positioned (top: 0 , left: 0.21 .sw, child: UndoRedoButton (su: suprovider,)),
42- // MODIFIED: Pass the WorkspaceProvider instance to the button
43- Positioned (top: 0 , right: 0.001 .sw, child: ExportProjectButton (su: suprovider, wp: provider)),
44-
45- Positioned (right: 0 , top: 0.10 .sh, child: ToolBar ()),
46-
47- Positioned (
48- bottom: 0. h,
49- right: 0. w,
50- child: ZoomControlButton (),
51- ),
24+ _WorkspaceDesktopState createState () => _WorkspaceDesktopState ();
25+ }
5226
53- Consumer2 <WorkspaceProvider , CanvasProvider >(
54- builder: (context, workspaceProvider, canvasProvider, child) {
55- return ListenableBuilder (
56- listenable: canvasProvider.transformationController,
57- builder: (context, child) {
58- if (workspaceProvider.shouldShowObjectToolbox) {
59- final selectedObject = workspaceProvider.canvasObjects[
60- workspaceProvider.currentlySelectedObjectId! ]! ;
61- final objectBounds = selectedObject.getBounds ();
62- final matrix =
63- canvasProvider.transformationController.value;
27+ class _WorkspaceDesktopState extends State <WorkspaceDesktop > {
28+ final FocusNode _focusNode = FocusNode ();
6429
65- final transformedTopCenter = matrix.transform3 (
66- vector_math.Vector3 (objectBounds.topCenter.dx,
67- objectBounds.topCenter.dy, 0 ));
30+ @override
31+ void initState () {
32+ super .initState ();
33+ // Request focus when the widget is first built
34+ _focusNode.requestFocus ();
35+ }
6836
69- final screenPosition = Offset (
70- transformedTopCenter.x, transformedTopCenter.y);
37+ @override
38+ void dispose () {
39+ // Clean up the focus node when the widget is disposed
40+ _focusNode.dispose ();
41+ super .dispose ();
42+ }
7143
72- const double toolboxWidth = 240 ;
73- const double toolboxHeight = 48 ;
44+ @override
45+ Widget build (BuildContext context) {
46+ // Define actions
47+ final Map <Type , Action <Intent >> actions = {
48+ PointerIntent : CallbackAction <PointerIntent >(
49+ onInvoke: (intent) {
50+ final provider = Provider .of <WorkspaceProvider >(
51+ context,
52+ listen: false ,
53+ );
54+ provider.changeDrawMode (DrawMode .pointer);
55+ return null ;
56+ },
57+ ),
58+ PanIntent : CallbackAction <PanIntent >(
59+ onInvoke: (intent) {
60+ final provider = Provider .of <WorkspaceProvider >(
61+ context,
62+ listen: false ,
63+ );
64+ provider.changeDrawMode (DrawMode .hand);
65+ return null ;
66+ },
67+ ),
68+ TextIntent : CallbackAction <TextIntent >(
69+ onInvoke: (intent) {
70+ final provider = Provider .of <WorkspaceProvider >(
71+ context,
72+ listen: false ,
73+ );
74+ provider.changeDrawMode (DrawMode .textBox);
75+ return null ;
76+ },
77+ ),
78+ };
7479
75- return Positioned (
76- left: screenPosition.dx - (toolboxWidth / 2 ),
77- top: screenPosition.dy - toolboxHeight - 15 ,
78- child: const NodeEditingToolbox (),
79- );
80- }
81- return const SizedBox .shrink ();
82- },
83- );
84- },
80+ return Consumer2 <WorkspaceProvider , SupabaseService >(
81+ builder: (context, provider, suprovider, child) {
82+ return Shortcuts (
83+ shortcuts: workspaceShortCut,
84+ child: Actions (
85+ actions: actions,
86+ child: Focus (
87+ focusNode: _focusNode,
88+ child: Scaffold (
89+ backgroundColor: provider.currentWorkspaceColor,
90+ body: GestureDetector (
91+ onTap: () {
92+ // This ensures focus is regained when the user taps on the canvas
93+ _focusNode.requestFocus ();
94+ },
95+ child: Padding (
96+ padding: EdgeInsets .symmetric (
97+ horizontal: 40. w,
98+ vertical: 40. h,
99+ ),
100+ child: Stack (
101+ clipBehavior: Clip .none,
102+ children: [
103+ const CanvasPage (),
104+ const WorkspaceDrawer (),
105+ SizedBox (width: 20. w),
106+ Positioned (
107+ top: 0 ,
108+ left: 0.21 .sw,
109+ child: UndoRedoButton (su: suprovider),
110+ ),
111+ Positioned (
112+ top: 0 ,
113+ right: 0.001 .sw,
114+ child: ExportProjectButton (
115+ su: suprovider,
116+ wp: provider,
117+ ),
118+ ),
119+ Positioned (right: 0 , top: 0.10 .sh, child: ToolBar ()),
120+ Positioned (
121+ bottom: 0. h,
122+ right: 0. w,
123+ child: ZoomControlButton (),
124+ ),
125+ Consumer2 <WorkspaceProvider , CanvasProvider >(
126+ builder: (
127+ context,
128+ workspaceProvider,
129+ canvasProvider,
130+ child,
131+ ) {
132+ return ListenableBuilder (
133+ listenable:
134+ canvasProvider.transformationController,
135+ builder: (context, child) {
136+ if (workspaceProvider.shouldShowObjectToolbox) {
137+ final selectedObject =
138+ workspaceProvider
139+ .canvasObjects[workspaceProvider
140+ .currentlySelectedObjectId! ]! ;
141+ final objectBounds =
142+ selectedObject.getBounds ();
143+ final matrix =
144+ canvasProvider
145+ .transformationController
146+ .value;
147+ final transformedTopCenter = matrix
148+ .transform3 (
149+ vector_math.Vector3 (
150+ objectBounds.topCenter.dx,
151+ objectBounds.topCenter.dy,
152+ 0 ,
153+ ),
154+ );
155+ final screenPosition = Offset (
156+ transformedTopCenter.x,
157+ transformedTopCenter.y,
158+ );
159+ const double toolboxWidth = 240 ;
160+ const double toolboxHeight = 48 ;
161+ return Positioned (
162+ left:
163+ screenPosition.dx - (toolboxWidth / 2 ),
164+ top: screenPosition.dy - toolboxHeight - 15 ,
165+ child: const NodeEditingToolbox (),
166+ );
167+ }
168+ return const SizedBox .shrink ();
169+ },
170+ );
171+ },
172+ ),
173+ const ObjectTextEditor (),
174+ ],
175+ ),
176+ ),
177+ ),
85178 ),
86-
87- const ObjectTextEditor (),
88- ],
179+ ),
89180 ),
90- ),
91- );
92- } );
181+ );
182+ },
183+ );
93184 }
94- }
185+ }
0 commit comments