Line data Source code
1 : // Copyright 2023 The terCAD team. All rights reserved. 2 : // Use of this source code is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file. 3 : 4 : import 'package:app_finance/_classes/controller/focus_controller.dart'; 5 : import 'package:app_finance/_classes/herald/app_zoom.dart'; 6 : import 'package:app_finance/_classes/structure/navigation/app_route.dart'; 7 : // import 'package:app_finance/pages/_interfaces/abstract_page_state.dart'; 8 : import 'package:flutter/gestures.dart'; 9 : import 'package:flutter/material.dart'; 10 : import 'package:flutter/services.dart'; 11 : import 'package:provider/provider.dart'; 12 : 13 : enum AppEvents { 14 : zoomIn, 15 : zoomOut, 16 : zoomReset, 17 : tipDrawer, 18 : newBill, 19 : edit, 20 : delete, 21 : back, 22 : } 23 : 24 : class InputControllerWrapper extends StatefulWidget { 25 3 : static final drawerKey = GlobalKey(); 26 : final Widget child; 27 : 28 1 : const InputControllerWrapper({ 29 : super.key, 30 : required this.child, 31 : }); 32 : 33 1 : @override 34 1 : InputControllerWrapperState createState() => InputControllerWrapperState(); 35 : } 36 : 37 : class InputControllerWrapperState extends State<InputControllerWrapper> { 38 : bool _ctrlPressed = false; 39 : late AppZoom zoom; 40 : final focus = FocusNode(); 41 : 42 1 : @override 43 : void dispose() { 44 2 : focus.dispose(); 45 1 : super.dispose(); 46 : } 47 : 48 0 : void handleEvent(AppEvents event) { 49 : switch (event) { 50 0 : case AppEvents.zoomOut: 51 0 : return onScaleUpdate(ScaleUpdateDetails(scale: 0.9)); 52 0 : case AppEvents.zoomIn: 53 0 : return onScaleUpdate(ScaleUpdateDetails(scale: 1.1)); 54 0 : case AppEvents.zoomReset: 55 0 : zoom.set(1.0); 56 : break; 57 0 : case AppEvents.tipDrawer: 58 0 : final render = InputControllerWrapper.drawerKey.currentContext?.findRenderObject(); 59 : if (render != null) { 60 0 : Scaffold.of(context).closeDrawer(); 61 : } else { 62 0 : Scaffold.of(context).openDrawer(); 63 : } 64 : break; 65 0 : case AppEvents.newBill: 66 0 : Navigator.of(context).pushNamed(AppRoute.billAddRoute); 67 : break; 68 0 : case AppEvents.back: 69 0 : if (Navigator.of(context).canPop()) { 70 0 : Navigator.of(context).pop(); 71 : } 72 : break; 73 0 : case AppEvents.edit: 74 0 : case AppEvents.delete: 75 : // TBD: FocusScope.of(context).focusedChild); 76 : break; 77 : } 78 : } 79 : 80 0 : void onKeyPressed(RawKeyEvent event) { 81 0 : if (event is RawKeyDownEvent) { 82 0 : if (event.isControlPressed) { 83 0 : if (event.logicalKey == LogicalKeyboardKey.minus) { 84 0 : return handleEvent(AppEvents.zoomOut); 85 : } 86 0 : if (event.logicalKey == LogicalKeyboardKey.equal) { 87 0 : return handleEvent(AppEvents.zoomIn); 88 : } 89 0 : if (event.logicalKey == LogicalKeyboardKey.digit0) { 90 0 : return handleEvent(AppEvents.zoomReset); 91 : } 92 0 : if (event.isKeyPressed(LogicalKeyboardKey.keyN)) { 93 0 : return handleEvent(AppEvents.newBill); 94 : } 95 0 : if (event.isKeyPressed(LogicalKeyboardKey.keyE)) { 96 0 : return handleEvent(AppEvents.edit); 97 : } 98 0 : if (event.isKeyPressed(LogicalKeyboardKey.keyD)) { 99 0 : return handleEvent(AppEvents.delete); 100 : } 101 0 : if (event.isKeyPressed(LogicalKeyboardKey.backspace)) { 102 0 : return handleEvent(AppEvents.back); 103 : } 104 0 : } else if (event.isShiftPressed) { 105 0 : if (event.isKeyPressed(LogicalKeyboardKey.enter)) { 106 0 : return handleEvent(AppEvents.tipDrawer); 107 : } 108 : } 109 : } 110 0 : if (event.logicalKey == LogicalKeyboardKey.controlLeft || event.logicalKey == LogicalKeyboardKey.controlRight) { 111 0 : setState(() => _ctrlPressed = event is RawKeyDownEvent); 112 : } 113 : } 114 : 115 0 : void onPointerSignal(PointerSignalEvent event) { 116 0 : if (_ctrlPressed && event is PointerScrollEvent) { 117 0 : handleEvent(event.scrollDelta.dy > 0 ? AppEvents.zoomOut : AppEvents.zoomIn); 118 : } 119 : } 120 : 121 0 : void onScaleUpdate(ScaleUpdateDetails details) { 122 : const step = 0.1; 123 0 : zoom.set(zoom.value + (details.scale > 1 ? step : -step)); 124 : } 125 : 126 1 : @override 127 : Widget build(BuildContext context) { 128 2 : zoom = Provider.of<AppZoom>(context, listen: false); 129 1 : return Listener( 130 1 : onPointerSignal: onPointerSignal, 131 1 : child: RawKeyboardListener( 132 3 : focusNode: FocusController.force ? focus : (focus..requestFocus()), 133 1 : onKey: onKeyPressed, 134 : //child: GestureDetector( 135 : // onScaleUpdate: onScaleUpdate, 136 2 : child: widget.child, 137 : //), 138 : ), 139 : ); 140 : } 141 : }