board.dart 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import 'package:flutter/material.dart';
  2. import 'package:provider/provider.dart';
  3. import 'flex/drag_target_inteceptor.dart';
  4. import 'flex/reorder_flex.dart';
  5. import 'phantom/phantom_controller.dart';
  6. import '../../flowy_board.dart';
  7. import '../rendering/board_overlay.dart';
  8. class Board extends StatelessWidget {
  9. /// The direction to use as the main axis.
  10. final Axis direction = Axis.vertical;
  11. /// How much space to place between children in a run in the main axis.
  12. /// Defaults to 10.0.
  13. final double spacing;
  14. /// How much space to place between the runs themselves in the cross axis.
  15. /// Defaults to 0.0.
  16. final double runSpacing;
  17. ///
  18. final Widget? background;
  19. ///
  20. final BoardColumnCardBuilder cardBuilder;
  21. ///
  22. final BoardColumnHeaderBuilder? headerBuilder;
  23. ///
  24. final BoardColumnFooterBuilder? footBuilder;
  25. ///
  26. final BoardDataController dataController;
  27. final BoxConstraints columnConstraints;
  28. ///
  29. final BoardPhantomController phantomController;
  30. Board({
  31. required this.dataController,
  32. required this.cardBuilder,
  33. this.spacing = 10.0,
  34. this.runSpacing = 0.0,
  35. this.background,
  36. this.footBuilder,
  37. this.headerBuilder,
  38. this.columnConstraints = const BoxConstraints(maxWidth: 200),
  39. Key? key,
  40. }) : phantomController = BoardPhantomController(delegate: dataController),
  41. super(key: key);
  42. @override
  43. Widget build(BuildContext context) {
  44. return ChangeNotifierProvider.value(
  45. value: dataController,
  46. child: Consumer<BoardDataController>(
  47. builder: (context, notifier, child) {
  48. return BoardContent(
  49. dataController: dataController,
  50. background: background,
  51. spacing: spacing,
  52. delegate: phantomController,
  53. columnConstraints: columnConstraints,
  54. cardBuilder: cardBuilder,
  55. footBuilder: footBuilder,
  56. headerBuilder: headerBuilder,
  57. phantomController: phantomController,
  58. onReorder: dataController.onReorder,
  59. );
  60. },
  61. ),
  62. );
  63. }
  64. }
  65. class BoardContent extends StatefulWidget {
  66. final ScrollController? scrollController;
  67. final OnDragStarted? onDragStarted;
  68. final OnReorder onReorder;
  69. final OnDragEnded? onDragEnded;
  70. final BoardDataController dataController;
  71. final Widget? background;
  72. final double spacing;
  73. final ReorderFlexConfig config;
  74. final BoxConstraints columnConstraints;
  75. ///
  76. final BoardColumnCardBuilder cardBuilder;
  77. ///
  78. final BoardColumnHeaderBuilder? headerBuilder;
  79. ///
  80. final BoardColumnFooterBuilder? footBuilder;
  81. final OverlapReorderFlexDragTargetDelegate delegate;
  82. final BoardPhantomController phantomController;
  83. const BoardContent({
  84. required this.onReorder,
  85. required this.delegate,
  86. required this.dataController,
  87. this.onDragStarted,
  88. this.onDragEnded,
  89. this.scrollController,
  90. this.background,
  91. this.spacing = 0.0,
  92. this.config = const ReorderFlexConfig(),
  93. required this.columnConstraints,
  94. required this.cardBuilder,
  95. this.footBuilder,
  96. this.headerBuilder,
  97. required this.phantomController,
  98. Key? key,
  99. }) : super(key: key);
  100. @override
  101. State<BoardContent> createState() => _BoardContentState();
  102. }
  103. class _BoardContentState extends State<BoardContent> {
  104. final GlobalKey _columnContainerOverlayKey =
  105. GlobalKey(debugLabel: '$BoardContent overlay key');
  106. late BoardOverlayEntry _overlayEntry;
  107. @override
  108. void initState() {
  109. _overlayEntry = BoardOverlayEntry(
  110. builder: (BuildContext context) {
  111. List<Widget> children =
  112. widget.dataController.columnDatas.map((columnData) {
  113. return _buildColumn(
  114. columnData.id,
  115. widget.dataController.columnIds,
  116. widget.dataController.columnController(columnData.id),
  117. );
  118. }).toList();
  119. final interceptor = OverlapReorderFlexDragTargetInteceptor(
  120. reorderFlexId: widget.dataController.identifier,
  121. acceptedReorderFlexId: widget.dataController.columnIds,
  122. delegate: widget.delegate,
  123. );
  124. Widget reorderFlex = ReorderFlex(
  125. key: widget.key,
  126. scrollController: widget.scrollController,
  127. config: widget.config,
  128. onDragStarted: widget.onDragStarted,
  129. onReorder: widget.onReorder,
  130. onDragEnded: widget.onDragEnded,
  131. dataSource: widget.dataController,
  132. direction: Axis.horizontal,
  133. spacing: widget.spacing,
  134. interceptor: interceptor,
  135. children: children,
  136. );
  137. return Stack(
  138. alignment: AlignmentDirectional.topStart,
  139. children: [
  140. if (widget.background != null) widget.background!,
  141. reorderFlex,
  142. ],
  143. );
  144. },
  145. opaque: false,
  146. );
  147. super.initState();
  148. }
  149. @override
  150. Widget build(BuildContext context) {
  151. return BoardOverlay(
  152. key: _columnContainerOverlayKey,
  153. initialEntries: [_overlayEntry],
  154. );
  155. }
  156. Widget _buildColumn(
  157. String columnId,
  158. List<String> acceptColumns,
  159. BoardColumnDataController dataController,
  160. ) {
  161. return ChangeNotifierProvider.value(
  162. key: ValueKey(columnId),
  163. value: dataController,
  164. child: Consumer<BoardColumnDataController>(
  165. builder: (context, value, child) {
  166. return ConstrainedBox(
  167. constraints: widget.columnConstraints,
  168. child: BoardColumnWidget(
  169. headerBuilder: widget.headerBuilder,
  170. footBuilder: widget.footBuilder,
  171. cardBuilder: widget.cardBuilder,
  172. acceptedColumns: acceptColumns,
  173. dataController: dataController,
  174. scrollController: ScrollController(),
  175. onReorder: (_, int fromIndex, int toIndex) {
  176. dataController.move(fromIndex, toIndex);
  177. },
  178. phantomController: widget.phantomController,
  179. ),
  180. );
  181. },
  182. ),
  183. );
  184. }
  185. }