|
@@ -4,7 +4,8 @@ import 'package:flutter/material.dart';
|
|
|
import 'package:provider/provider.dart';
|
|
|
import '../../flowy_board.dart';
|
|
|
|
|
|
-import 'column_container.dart';
|
|
|
+import '../rendering/board_overlay.dart';
|
|
|
+import 'flex/drag_target_inteceptor.dart';
|
|
|
import 'flex/reorder_flex.dart';
|
|
|
import 'phantom/phantom_controller.dart';
|
|
|
|
|
@@ -57,22 +58,24 @@ class Board extends StatelessWidget {
|
|
|
Widget build(BuildContext context) {
|
|
|
return ChangeNotifierProvider.value(
|
|
|
value: dataController,
|
|
|
- child: Consumer(
|
|
|
+ child: Consumer<BoardDataController>(
|
|
|
builder: (context, notifier, child) {
|
|
|
- List<Widget> children = [];
|
|
|
- List<String> acceptColumns =
|
|
|
- dataController.columnControllers.keys.toList();
|
|
|
+ List<Widget> children = dataController.columnDatas.map((columnData) {
|
|
|
+ final controller = dataController.columnController(columnData.id);
|
|
|
|
|
|
- dataController.columnControllers.forEach((columnId, controller) {
|
|
|
- Widget child = _buildColumn(columnId, acceptColumns, controller);
|
|
|
- children.add(child);
|
|
|
- });
|
|
|
+ return _buildColumn(
|
|
|
+ columnData.id,
|
|
|
+ dataController.columnIds,
|
|
|
+ controller,
|
|
|
+ );
|
|
|
+ }).toList();
|
|
|
|
|
|
return BoardColumnContainer(
|
|
|
- onReorder: (fromIndex, toIndex) {},
|
|
|
+ onReorder: dataController.onReorder,
|
|
|
boardDataController: dataController,
|
|
|
background: background,
|
|
|
spacing: spacing,
|
|
|
+ delegate: phantomController,
|
|
|
children: children,
|
|
|
);
|
|
|
},
|
|
@@ -97,7 +100,7 @@ class Board extends StatelessWidget {
|
|
|
headerBuilder: headerBuilder,
|
|
|
footBuilder: footBuilder,
|
|
|
cardBuilder: cardBuilder,
|
|
|
- acceptColumns: acceptColumns,
|
|
|
+ acceptedColumns: acceptColumns,
|
|
|
dataController: dataController,
|
|
|
scrollController: ScrollController(),
|
|
|
onReorder: (_, int fromIndex, int toIndex) {
|
|
@@ -114,33 +117,133 @@ class Board extends StatelessWidget {
|
|
|
|
|
|
class BoardDataController extends ChangeNotifier
|
|
|
with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlextDataSource {
|
|
|
- final LinkedHashMap<String, BoardColumnData> columnDatas = LinkedHashMap();
|
|
|
- final LinkedHashMap<String, BoardColumnDataController> columnControllers =
|
|
|
+ final List<BoardColumnData> _columnDatas = [];
|
|
|
+
|
|
|
+ List<BoardColumnData> get columnDatas => _columnDatas;
|
|
|
+
|
|
|
+ List<String> get columnIds =>
|
|
|
+ _columnDatas.map((columnData) => columnData.id).toList();
|
|
|
+
|
|
|
+ final LinkedHashMap<String, BoardColumnDataController> _columnControllers =
|
|
|
LinkedHashMap();
|
|
|
|
|
|
BoardDataController();
|
|
|
|
|
|
void setColumnData(BoardColumnData columnData) {
|
|
|
final controller = BoardColumnDataController(columnData: columnData);
|
|
|
- columnDatas[columnData.id] = columnData;
|
|
|
- columnControllers[columnData.id] = controller;
|
|
|
+ _columnDatas.add(columnData);
|
|
|
+ _columnControllers[columnData.id] = controller;
|
|
|
+ }
|
|
|
+
|
|
|
+ BoardColumnDataController columnController(String columnId) {
|
|
|
+ return _columnControllers[columnId]!;
|
|
|
+ }
|
|
|
+
|
|
|
+ void onReorder(int fromIndex, int toIndex) {
|
|
|
+ final columnData = _columnDatas.removeAt(fromIndex);
|
|
|
+ _columnDatas.insert(toIndex, columnData);
|
|
|
+ notifyListeners();
|
|
|
}
|
|
|
|
|
|
@override
|
|
|
List<Object?> get props {
|
|
|
- return [columnDatas.values];
|
|
|
+ return [_columnDatas];
|
|
|
}
|
|
|
|
|
|
@override
|
|
|
BoardColumnDataController? controller(String columnId) {
|
|
|
- return columnControllers[columnId];
|
|
|
+ return _columnControllers[columnId];
|
|
|
}
|
|
|
|
|
|
@override
|
|
|
String get identifier => '$BoardDataController';
|
|
|
|
|
|
@override
|
|
|
- List<ReoderFlextItem> get items => columnDatas.values.toList();
|
|
|
+ List<ReoderFlexItem> get items => _columnDatas;
|
|
|
+}
|
|
|
+
|
|
|
+class BoardColumnContainer extends StatefulWidget {
|
|
|
+ final ScrollController? scrollController;
|
|
|
+ final OnDragStarted? onDragStarted;
|
|
|
+ final OnReorder onReorder;
|
|
|
+ final OnDragEnded? onDragEnded;
|
|
|
+ final BoardDataController boardDataController;
|
|
|
+ final List<Widget> children;
|
|
|
+ final Widget? background;
|
|
|
+ final double spacing;
|
|
|
+ final ReorderFlexConfig config;
|
|
|
+
|
|
|
+ final OverlapReorderFlexDragTargetDelegate delegate;
|
|
|
+
|
|
|
+ const BoardColumnContainer({
|
|
|
+ required this.onReorder,
|
|
|
+ required this.children,
|
|
|
+ required this.delegate,
|
|
|
+ required this.boardDataController,
|
|
|
+ this.onDragStarted,
|
|
|
+ this.onDragEnded,
|
|
|
+ this.scrollController,
|
|
|
+ this.background,
|
|
|
+ this.spacing = 0.0,
|
|
|
+ this.config = const ReorderFlexConfig(),
|
|
|
+ Key? key,
|
|
|
+ }) : super(key: key);
|
|
|
+
|
|
|
+ @override
|
|
|
+ State<BoardColumnContainer> createState() => _BoardColumnContainerState();
|
|
|
}
|
|
|
|
|
|
-class BoardDataIdentifier {}
|
|
|
+class _BoardColumnContainerState extends State<BoardColumnContainer> {
|
|
|
+ final GlobalKey _columnContainerOverlayKey =
|
|
|
+ GlobalKey(debugLabel: '$BoardColumnContainer overlay key');
|
|
|
+ late BoardOverlayEntry _overlayEntry;
|
|
|
+
|
|
|
+ @override
|
|
|
+ void initState() {
|
|
|
+ _overlayEntry = BoardOverlayEntry(
|
|
|
+ builder: (BuildContext context) {
|
|
|
+ final interceptor = OverlapReorderFlexDragTargetInteceptor(
|
|
|
+ reorderFlexId: widget.boardDataController.identifier,
|
|
|
+ acceptedReorderFlexId: widget.boardDataController.columnIds,
|
|
|
+ delegate: widget.delegate,
|
|
|
+ );
|
|
|
+
|
|
|
+ Widget reorderFlex = ReorderFlex(
|
|
|
+ key: widget.key,
|
|
|
+ scrollController: widget.scrollController,
|
|
|
+ config: widget.config,
|
|
|
+ onDragStarted: widget.onDragStarted,
|
|
|
+ onReorder: widget.onReorder,
|
|
|
+ onDragEnded: widget.onDragEnded,
|
|
|
+ dataSource: widget.boardDataController,
|
|
|
+ direction: Axis.horizontal,
|
|
|
+ spacing: widget.spacing,
|
|
|
+ interceptor: interceptor,
|
|
|
+ children: widget.children,
|
|
|
+ );
|
|
|
+
|
|
|
+ return _wrapStack(reorderFlex);
|
|
|
+ },
|
|
|
+ opaque: false,
|
|
|
+ );
|
|
|
+ super.initState();
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return BoardOverlay(
|
|
|
+ key: _columnContainerOverlayKey,
|
|
|
+ initialEntries: [_overlayEntry],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget _wrapStack(Widget child) {
|
|
|
+ return Stack(
|
|
|
+ alignment: AlignmentDirectional.topStart,
|
|
|
+ children: [
|
|
|
+ if (widget.background != null) widget.background!,
|
|
|
+ child,
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|