ANTIPALSU Label template editor using flutter

main.dart 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import 'dart:math';
  2. import 'package:defer_pointer/defer_pointer.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_canvas_editor/canvas_setup_page.dart';
  5. import 'package:flutter_canvas_editor/history.dart';
  6. import 'package:flutter_canvas_editor/providers/editor.dart';
  7. import 'package:flutter_canvas_editor/snaptest_page.dart';
  8. import 'package:flutter_canvas_editor/test_page.dart';
  9. import 'package:flutter_canvas_editor/widgets/elements.dart';
  10. import 'package:provider/provider.dart';
  11. import 'package:toastification/toastification.dart';
  12. import 'resizeable_element.dart';
  13. import 'widgets/toolbar.dart';
  14. void main() {
  15. runApp(MyApp());
  16. }
  17. class MyApp extends StatelessWidget {
  18. @override
  19. Widget build(BuildContext context) {
  20. return MultiProvider(
  21. providers: [
  22. ChangeNotifierProvider(create: (_) => Editor()),
  23. ChangeNotifierProvider(create: (_) => EditorTest()),
  24. ],
  25. child: ToastificationWrapper(
  26. child: MaterialApp(
  27. theme: ThemeData(
  28. textTheme: TextTheme(
  29. // bodyMedium: TextStyle(fontSize: 20)
  30. )
  31. ),
  32. home: HomePage(),
  33. ),
  34. ),
  35. );
  36. }
  37. }
  38. class HomePage extends StatefulWidget {
  39. @override
  40. State<HomePage> createState() => _HomePageState();
  41. }
  42. class _HomePageState extends State<HomePage> {
  43. double initialScale = 1;
  44. // CanvasProperty _canvasProperty = CanvasProperty(
  45. // width: 0,
  46. // height: 0,
  47. // );
  48. String? selectedElmId;
  49. bool _showResetPosition = false;
  50. @override
  51. void initState() {
  52. super.initState();
  53. WidgetsBinding.instance!.addPostFrameCallback((_) {
  54. // _canvasProperty = Provider.of<Editor>(context, listen: false).canvasProperty;
  55. setInitialZoom();
  56. });
  57. setTransformControllerListener();
  58. }
  59. @override
  60. void dispose() {
  61. Provider.of<Editor>(context, listen: false).disposeCanvasTransformationController();
  62. super.dispose();
  63. }
  64. // functions
  65. void setInitialZoom() {
  66. Provider.of<Editor>(context, listen: false).setCanvasTransformationInitialZoom(context);
  67. }
  68. void setTransformControllerListener() {
  69. Provider.of<Editor>(context, listen: false).canvasTransformationController.addListener(() {
  70. if (!_showResetPosition && (Provider.of<Editor>(context, listen: false).canvasTransformationController.value != (Matrix4.identity()..scale(initialScale)))) {
  71. print('triggered');
  72. setState(() {
  73. _showResetPosition = true;
  74. });
  75. }
  76. });
  77. }
  78. @override
  79. Widget build(BuildContext context) {
  80. return DeferredPointerHandler(
  81. link: Provider.of<Editor>(context).textboxResizerDeferredPointerHandlerLink,
  82. child: Scaffold(
  83. backgroundColor: Colors.grey,
  84. appBar: AppBar(
  85. title: Text('Template Editor'),
  86. actions: [
  87. IconButton(
  88. onPressed: Provider.of<Editor>(context, listen: false).stateStack.length <= 1 ? null : () {
  89. Provider.of<Editor>(context, listen: false).undo();
  90. },
  91. icon: Icon(Icons.undo)
  92. ),
  93. IconButton(
  94. onPressed: Provider.of<Editor>(context, listen: false).redoStack.isEmpty ? null : () {
  95. Provider.of<Editor>(context, listen: false).redo();
  96. },
  97. icon: Icon(Icons.redo)
  98. ),
  99. // ! DEBUG BUTTON
  100. IconButton(
  101. onPressed: () {
  102. Provider.of<Editor>(context, listen: false).buildJSON();
  103. },
  104. icon: Icon(Icons.bug_report_outlined)
  105. ),
  106. IconButton(
  107. onPressed: () {
  108. Navigator.push(
  109. context,
  110. MaterialPageRoute(builder: (context) => CanvasSetupPage(),)
  111. );
  112. },
  113. icon: Icon(Icons.link)
  114. )
  115. ],
  116. ),
  117. body: Column(
  118. children: [
  119. Expanded(
  120. child: GestureDetector(
  121. onTap: () {
  122. print('Main Gesture Detector Tapped!');
  123. setState(() {
  124. Provider.of<Editor>(context, listen: false).unSelectElm();
  125. });
  126. },
  127. child: Stack(
  128. children: [
  129. InteractiveViewer(
  130. transformationController: Provider.of<Editor>(context).canvasTransformationController,
  131. boundaryMargin: EdgeInsets.all(double.infinity),
  132. maxScale: 4,
  133. minScale: 0.1,
  134. constrained: false,
  135. child: DeferredPointerHandler(
  136. child: Center(
  137. child: Padding(
  138. padding: const EdgeInsets.all(16),
  139. child: CustomPaint(
  140. size: Size(Provider.of<Editor>(context).canvasProperty.width, Provider.of<Editor>(context).canvasProperty.height),
  141. foregroundPainter: CanvasAlignmentHelper(
  142. showHorizontalCenterLine: Provider.of<Editor>(context).shouldShowHorizontalCenterLine,
  143. showVerticalCenterLine: Provider.of<Editor>(context).shouldShowVerticalCenterLine
  144. ),
  145. child: Container(
  146. // margin: EdgeInsets.all(16),
  147. color: Colors.white,
  148. height: Provider.of<Editor>(context).canvasProperty.height,
  149. width: Provider.of<Editor>(context).canvasProperty.width,
  150. child: Stack(
  151. children: [
  152. for (ElementState elementProperty in Provider.of<Editor>(context).currentElementsState) ... [
  153. ElementWidget(
  154. elementProperty: elementProperty,
  155. canvasProperty: Provider.of<Editor>(context).canvasProperty,
  156. globalKey: elementProperty.elementKey,
  157. )
  158. ]
  159. ],
  160. ),
  161. ),
  162. ),
  163. ),
  164. ),
  165. ),
  166. ),
  167. if (_showResetPosition) Positioned(
  168. bottom: 16,
  169. right: 16,
  170. child: IconButton.filled(
  171. tooltip: 'Reset Position',
  172. onPressed: () {
  173. Provider.of<Editor>(context, listen: false).resetCanvasTransformationScale();
  174. _showResetPosition = false;
  175. setState(() {});
  176. },
  177. icon: Icon(Icons.center_focus_strong),
  178. color: Colors.white,
  179. ),
  180. )
  181. ],
  182. ),
  183. ),
  184. ),
  185. // Toolbar
  186. ToolbarWidget()
  187. ],
  188. ),
  189. ),
  190. );
  191. }
  192. }
  193. class CanvasProperty {
  194. double width;
  195. double height;
  196. CanvasProperty({
  197. required this.width,
  198. required this.height,
  199. });
  200. Offset getCanvasCenterPoint() {
  201. return Offset(width / 2, height / 2);
  202. }
  203. }
  204. class CanvasAlignmentHelper extends CustomPainter {
  205. CanvasAlignmentHelper({required this.showHorizontalCenterLine, required this.showVerticalCenterLine});
  206. bool showHorizontalCenterLine;
  207. bool showVerticalCenterLine;
  208. @override
  209. void paint(Canvas canvas, Size size) {
  210. // ? horizontal center line
  211. if (showHorizontalCenterLine) {
  212. canvas.drawLine(
  213. Offset(size.width / 2, 0),
  214. Offset(size.width / 2, size.height),
  215. Paint()
  216. ..color = Colors.orange
  217. ..strokeWidth = 1.5
  218. );
  219. }
  220. // ? vertial center line
  221. if (showVerticalCenterLine) {
  222. canvas.drawLine(
  223. Offset(0, size.height / 2),
  224. Offset(size.width, size.height / 2),
  225. Paint()
  226. ..color = Colors.orange
  227. ..strokeWidth = 1.5
  228. );
  229. }
  230. }
  231. @override
  232. bool shouldRepaint(covariant CustomPainter oldDelegate) {
  233. return true;
  234. }
  235. }