mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add documentation
This commit is contained in:
parent
2e0256f305
commit
9e4dbc53f7
@ -9,7 +9,7 @@ class MultiBoardListExample extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
||||
final BoardDataController boardData = BoardDataController();
|
||||
final BoardDataController boardDataController = BoardDataController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -34,9 +34,9 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
||||
TextItem("D"),
|
||||
]);
|
||||
|
||||
boardData.setColumnData(column1);
|
||||
boardData.setColumnData(column2);
|
||||
boardData.setColumnData(column3);
|
||||
boardDataController.setColumnData(column1);
|
||||
boardDataController.setColumnData(column2);
|
||||
boardDataController.setColumnData(column3);
|
||||
|
||||
super.initState();
|
||||
}
|
||||
@ -44,7 +44,7 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Board(
|
||||
dataController: boardData,
|
||||
dataController: boardDataController,
|
||||
background: Container(color: Colors.red),
|
||||
footBuilder: (context, columnData) {
|
||||
return Container(
|
||||
|
@ -67,7 +67,7 @@ class Board extends StatelessWidget {
|
||||
footBuilder: footBuilder,
|
||||
headerBuilder: headerBuilder,
|
||||
phantomController: phantomController,
|
||||
onReorder: dataController.onReorder,
|
||||
onReorder: dataController.moveColumn,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -99,7 +99,7 @@ class BoardContent extends StatefulWidget {
|
||||
|
||||
final BoardPhantomController phantomController;
|
||||
|
||||
const BoardContent({
|
||||
BoardContent({
|
||||
required this.onReorder,
|
||||
required this.delegate,
|
||||
required this.dataController,
|
||||
@ -107,22 +107,23 @@ class BoardContent extends StatefulWidget {
|
||||
this.onDragEnded,
|
||||
this.scrollController,
|
||||
this.background,
|
||||
this.spacing = 0.0,
|
||||
this.config = const ReorderFlexConfig(),
|
||||
this.spacing = 10.0,
|
||||
required this.columnConstraints,
|
||||
required this.cardBuilder,
|
||||
this.footBuilder,
|
||||
this.headerBuilder,
|
||||
required this.phantomController,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
}) : config = ReorderFlexConfig(spacing: spacing),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
State<BoardContent> createState() => _BoardContentState();
|
||||
}
|
||||
|
||||
class _BoardContentState extends State<BoardContent> {
|
||||
final GlobalKey _columnContainerOverlayKey = GlobalKey(debugLabel: '$BoardContent overlay key');
|
||||
final GlobalKey _columnContainerOverlayKey =
|
||||
GlobalKey(debugLabel: '$BoardContent overlay key');
|
||||
late BoardOverlayEntry _overlayEntry;
|
||||
|
||||
@override
|
||||
@ -144,7 +145,6 @@ class _BoardContentState extends State<BoardContent> {
|
||||
onDragEnded: widget.onDragEnded,
|
||||
dataSource: widget.dataController,
|
||||
direction: Axis.horizontal,
|
||||
spacing: widget.spacing,
|
||||
interceptor: interceptor,
|
||||
children: _buildColumns(),
|
||||
);
|
||||
@ -171,36 +171,54 @@ class _BoardContentState extends State<BoardContent> {
|
||||
}
|
||||
|
||||
List<Widget> _buildColumns() {
|
||||
final acceptColumns = widget.dataController.columnIds;
|
||||
final List<Widget> children = widget.dataController.columnDatas.map(
|
||||
(columnData) {
|
||||
final dataSource = _BoardColumnDataSourceImpl(
|
||||
columnId: columnData.id,
|
||||
dataController: widget.dataController,
|
||||
);
|
||||
|
||||
final List<Widget> children = widget.dataController.columnDatas.map((columnData) {
|
||||
final dataController = widget.dataController.columnController(columnData.id);
|
||||
|
||||
return ChangeNotifierProvider.value(
|
||||
key: ValueKey(columnData.id),
|
||||
value: dataController,
|
||||
child: Consumer<BoardColumnDataController>(
|
||||
builder: (context, value, child) {
|
||||
return ConstrainedBox(
|
||||
constraints: widget.columnConstraints,
|
||||
child: BoardColumnWidget(
|
||||
headerBuilder: widget.headerBuilder,
|
||||
footBuilder: widget.footBuilder,
|
||||
cardBuilder: widget.cardBuilder,
|
||||
acceptedColumns: acceptColumns,
|
||||
dataController: dataController,
|
||||
scrollController: ScrollController(),
|
||||
phantomController: widget.phantomController,
|
||||
onReorder: (_, int fromIndex, int toIndex) {
|
||||
dataController.move(fromIndex, toIndex);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}).toList();
|
||||
return ChangeNotifierProvider.value(
|
||||
key: ValueKey(columnData.id),
|
||||
value: widget.dataController.columnController(columnData.id),
|
||||
child: Consumer<BoardColumnDataController>(
|
||||
builder: (context, value, child) {
|
||||
return ConstrainedBox(
|
||||
constraints: widget.columnConstraints,
|
||||
child: BoardColumnWidget(
|
||||
headerBuilder: widget.headerBuilder,
|
||||
footBuilder: widget.footBuilder,
|
||||
cardBuilder: widget.cardBuilder,
|
||||
dataSource: dataSource,
|
||||
scrollController: ScrollController(),
|
||||
phantomController: widget.phantomController,
|
||||
onReorder: widget.dataController.moveColumnItem,
|
||||
spacing: 10,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList();
|
||||
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
class _BoardColumnDataSourceImpl extends BoardColumnDataDataSource {
|
||||
String columnId;
|
||||
final BoardDataController dataController;
|
||||
|
||||
_BoardColumnDataSourceImpl({
|
||||
required this.columnId,
|
||||
required this.dataController,
|
||||
});
|
||||
|
||||
@override
|
||||
BoardColumnData get columnData =>
|
||||
dataController.columnController(columnId).columnData;
|
||||
|
||||
@override
|
||||
List<String> get acceptedColumnIds => dataController.columnIds;
|
||||
}
|
||||
|
@ -1,29 +1,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../rendering/board_overlay.dart';
|
||||
import '../../utils/log.dart';
|
||||
import '../phantom/phantom_controller.dart';
|
||||
import '../flex/reorder_flex.dart';
|
||||
import '../flex/drag_target_inteceptor.dart';
|
||||
import 'data_controller.dart';
|
||||
|
||||
typedef OnColumnDragStarted = void Function(int index);
|
||||
|
||||
typedef OnColumnDragEnded = void Function(String listId);
|
||||
|
||||
typedef OnColumnReorder = void Function(
|
||||
String listId, int fromIndex, int toIndex);
|
||||
String listId,
|
||||
int fromIndex,
|
||||
int toIndex,
|
||||
);
|
||||
|
||||
typedef OnColumnDeleted = void Function(String listId, int deletedIndex);
|
||||
|
||||
typedef OnColumnInserted = void Function(String listId, int insertedIndex);
|
||||
|
||||
typedef BoardColumnCardBuilder = Widget Function(
|
||||
BuildContext context, ColumnItem item);
|
||||
BuildContext context,
|
||||
ColumnItem item,
|
||||
);
|
||||
|
||||
typedef BoardColumnHeaderBuilder = Widget Function(
|
||||
BuildContext context, BoardColumnData columnData);
|
||||
BuildContext context,
|
||||
BoardColumnData columnData,
|
||||
);
|
||||
|
||||
typedef BoardColumnFooterBuilder = Widget Function(
|
||||
BuildContext context, BoardColumnData columnData);
|
||||
BuildContext context,
|
||||
BoardColumnData columnData,
|
||||
);
|
||||
|
||||
abstract class BoardColumnDataDataSource extends ReoderFlextDataSource {
|
||||
BoardColumnData get columnData;
|
||||
|
||||
List<String> get acceptedColumnIds;
|
||||
|
||||
@override
|
||||
String get identifier => columnData.id;
|
||||
|
||||
@override
|
||||
UnmodifiableListView<ColumnItem> get items => columnData.items;
|
||||
|
||||
void debugPrint() {
|
||||
String msg = '[$BoardColumnDataDataSource] $columnData data: ';
|
||||
for (var element in items) {
|
||||
msg = '$msg$element,';
|
||||
}
|
||||
|
||||
Log.debug(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/// [BoardColumnWidget] represents the column of the Board.
|
||||
///
|
||||
class BoardColumnWidget extends StatefulWidget {
|
||||
final BoardColumnDataController dataController;
|
||||
final BoardColumnDataDataSource dataSource;
|
||||
final ScrollController? scrollController;
|
||||
final ReorderFlexConfig config;
|
||||
|
||||
@ -33,9 +71,7 @@ class BoardColumnWidget extends StatefulWidget {
|
||||
|
||||
final BoardPhantomController phantomController;
|
||||
|
||||
String get columnId => dataController.identifier;
|
||||
|
||||
final List<String> acceptedColumns;
|
||||
String get columnId => dataSource.columnData.id;
|
||||
|
||||
final BoardColumnCardBuilder cardBuilder;
|
||||
|
||||
@ -43,23 +79,20 @@ class BoardColumnWidget extends StatefulWidget {
|
||||
|
||||
final BoardColumnFooterBuilder? footBuilder;
|
||||
|
||||
final double? spacing;
|
||||
|
||||
const BoardColumnWidget({
|
||||
BoardColumnWidget({
|
||||
Key? key,
|
||||
this.headerBuilder,
|
||||
this.footBuilder,
|
||||
required this.cardBuilder,
|
||||
required this.onReorder,
|
||||
required this.dataController,
|
||||
required this.dataSource,
|
||||
required this.phantomController,
|
||||
required this.acceptedColumns,
|
||||
this.config = const ReorderFlexConfig(),
|
||||
this.spacing,
|
||||
this.onDragStarted,
|
||||
this.scrollController,
|
||||
this.onDragEnded,
|
||||
}) : super(key: key);
|
||||
double? spacing,
|
||||
}) : config = ReorderFlexConfig(spacing: spacing),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
State<BoardColumnWidget> createState() => _BoardColumnWidgetState();
|
||||
@ -75,20 +108,20 @@ class _BoardColumnWidgetState extends State<BoardColumnWidget> {
|
||||
void initState() {
|
||||
_overlayEntry = BoardOverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
final children = widget.dataController.items
|
||||
final children = widget.dataSource.columnData.items
|
||||
.map((item) => _buildWidget(context, item))
|
||||
.toList();
|
||||
|
||||
final header = widget.headerBuilder
|
||||
?.call(context, widget.dataController.columnData);
|
||||
final header =
|
||||
widget.headerBuilder?.call(context, widget.dataSource.columnData);
|
||||
|
||||
final footer =
|
||||
widget.footBuilder?.call(context, widget.dataController.columnData);
|
||||
widget.footBuilder?.call(context, widget.dataSource.columnData);
|
||||
|
||||
final interceptor = CrossReorderFlexDragTargetInterceptor(
|
||||
reorderFlexId: widget.columnId,
|
||||
delegate: widget.phantomController,
|
||||
acceptedReorderFlexIds: widget.acceptedColumns,
|
||||
acceptedReorderFlexIds: widget.dataSource.acceptedColumnIds,
|
||||
draggableTargetBuilder: PhantomDraggableBuilder(),
|
||||
);
|
||||
|
||||
@ -109,11 +142,10 @@ class _BoardColumnWidgetState extends State<BoardColumnWidget> {
|
||||
onDragEnded: () {
|
||||
widget.phantomController.columnEndDragging(widget.columnId);
|
||||
widget.onDragEnded?.call(widget.columnId);
|
||||
widget.dataController.debugPrintItems();
|
||||
widget.dataSource.debugPrint();
|
||||
},
|
||||
dataSource: widget.dataController,
|
||||
dataSource: widget.dataSource,
|
||||
interceptor: interceptor,
|
||||
spacing: widget.spacing,
|
||||
children: children,
|
||||
);
|
||||
|
||||
|
@ -9,36 +9,18 @@ abstract class ColumnItem extends ReoderFlexItem {
|
||||
bool get isPhantom => false;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
if (isPhantom) {
|
||||
return 'phantom:$id';
|
||||
} else {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
String toString() => id;
|
||||
}
|
||||
|
||||
class BoardColumnData extends ReoderFlexItem with EquatableMixin {
|
||||
@override
|
||||
final String id;
|
||||
final List<ColumnItem> _items;
|
||||
|
||||
BoardColumnData({
|
||||
required this.id,
|
||||
required List<ColumnItem> items,
|
||||
}) : _items = items;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, ..._items];
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Column$id';
|
||||
}
|
||||
}
|
||||
|
||||
class BoardColumnDataController extends ChangeNotifier
|
||||
with EquatableMixin, ReoderFlextDataSource {
|
||||
/// [BoardColumnDataController] is used to handle the [BoardColumnData].
|
||||
/// * Remove an item by calling [removeAt] method.
|
||||
/// * Move item to another position by calling [move] method.
|
||||
/// * Insert item to index by calling [insert] method
|
||||
/// * Replace item at index by calling [replace] method.
|
||||
///
|
||||
/// All there operations will notify listeners by default.
|
||||
///
|
||||
class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
|
||||
final BoardColumnData columnData;
|
||||
|
||||
BoardColumnDataController({
|
||||
@ -48,7 +30,18 @@ class BoardColumnDataController extends ChangeNotifier
|
||||
@override
|
||||
List<Object?> get props => columnData.props;
|
||||
|
||||
/// Returns the readonly List<ColumnItem>
|
||||
UnmodifiableListView<ColumnItem> get items =>
|
||||
UnmodifiableListView(columnData.items);
|
||||
|
||||
/// Remove the item at [index].
|
||||
/// * [index] the index of the item you want to remove
|
||||
/// * [notify] the default value of [notify] is true, it will notify the
|
||||
/// listener. Set to [false] if you do not want to notify the listeners.
|
||||
///
|
||||
ColumnItem removeAt(int index, {bool notify = true}) {
|
||||
assert(index >= 0);
|
||||
|
||||
Log.debug('[$BoardColumnDataController] $columnData remove item at $index');
|
||||
final item = columnData._items.removeAt(index);
|
||||
if (notify) {
|
||||
@ -57,7 +50,16 @@ class BoardColumnDataController extends ChangeNotifier
|
||||
return item;
|
||||
}
|
||||
|
||||
int removeWhere(bool Function(ColumnItem) condition) {
|
||||
return items.indexWhere(condition);
|
||||
}
|
||||
|
||||
/// Move the item from [fromIndex] to [toIndex]. It will do nothing if the
|
||||
/// [fromIndex] equal to the [toIndex].
|
||||
void move(int fromIndex, int toIndex) {
|
||||
assert(fromIndex >= 0);
|
||||
assert(toIndex >= 0);
|
||||
|
||||
if (fromIndex == toIndex) {
|
||||
return;
|
||||
}
|
||||
@ -68,7 +70,12 @@ class BoardColumnDataController extends ChangeNotifier
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Insert an item to [index] and notify the listen if the value of [notify]
|
||||
/// is true.
|
||||
///
|
||||
/// The default value of [notify] is true.
|
||||
void insert(int index, ColumnItem item, {bool notify = true}) {
|
||||
assert(index >= 0);
|
||||
Log.debug(
|
||||
'[$BoardColumnDataController] $columnData insert $item at $index');
|
||||
|
||||
@ -83,26 +90,35 @@ class BoardColumnDataController extends ChangeNotifier
|
||||
}
|
||||
}
|
||||
|
||||
void replace(int index, ColumnItem item) {
|
||||
/// Replace the item at index with the [newItem].
|
||||
void replace(int index, ColumnItem newItem) {
|
||||
final removedItem = columnData._items.removeAt(index);
|
||||
columnData._items.insert(index, item);
|
||||
columnData._items.insert(index, newItem);
|
||||
Log.debug(
|
||||
'[$BoardColumnDataController] $columnData replace $removedItem with $item at $index');
|
||||
'[$BoardColumnDataController] $columnData replace $removedItem with $newItem at $index');
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void debugPrintItems() {
|
||||
String msg = '[$BoardColumnDataController] $columnData data: ';
|
||||
for (var element in items) {
|
||||
msg = '$msg$element,';
|
||||
}
|
||||
|
||||
Log.debug(msg);
|
||||
}
|
||||
|
||||
@override
|
||||
List<ColumnItem> get items => UnmodifiableListView(columnData._items);
|
||||
|
||||
@override
|
||||
String get identifier => columnData.id;
|
||||
}
|
||||
|
||||
/// [BoardColumnData] represents the data of each Column of the Board.
|
||||
class BoardColumnData extends ReoderFlexItem with EquatableMixin {
|
||||
@override
|
||||
final String id;
|
||||
final List<ColumnItem> _items;
|
||||
|
||||
BoardColumnData({
|
||||
required this.id,
|
||||
required List<ColumnItem> items,
|
||||
}) : _items = items;
|
||||
|
||||
/// Returns the readonly List<ColumnItem>
|
||||
UnmodifiableListView<ColumnItem> get items => UnmodifiableListView(_items);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, ..._items];
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Column$id';
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import 'dart:collection';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../flowy_board.dart';
|
||||
import '../utils/log.dart';
|
||||
import 'flex/reorder_flex.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'phantom/phantom_controller.dart';
|
||||
@ -31,12 +32,35 @@ class BoardDataController extends ChangeNotifier
|
||||
return _columnControllers[columnId]!;
|
||||
}
|
||||
|
||||
void onReorder(int fromIndex, int toIndex) {
|
||||
void moveColumn(int fromIndex, int toIndex) {
|
||||
final columnData = _columnDatas.removeAt(fromIndex);
|
||||
_columnDatas.insert(toIndex, columnData);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void moveColumnItem(String columnId, int fromIndex, int toIndex) {
|
||||
final columnController = _columnControllers[columnId];
|
||||
assert(columnController != null);
|
||||
if (columnController != null) {
|
||||
columnController.move(fromIndex, toIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void swapColumnItem(
|
||||
String fromColumnId,
|
||||
int fromColumnIndex,
|
||||
String toColumnId,
|
||||
int toColumnIndex,
|
||||
) {
|
||||
final item = columnController(fromColumnId).removeAt(fromColumnIndex);
|
||||
|
||||
assert(
|
||||
columnController(toColumnId).items[toColumnIndex] is PhantomColumnItem);
|
||||
|
||||
columnController(toColumnId).replace(toColumnIndex, item);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props {
|
||||
return [_columnDatas];
|
||||
@ -51,5 +75,42 @@ class BoardDataController extends ChangeNotifier
|
||||
String get identifier => '$BoardDataController';
|
||||
|
||||
@override
|
||||
List<ReoderFlexItem> get items => _columnDatas;
|
||||
UnmodifiableListView<ReoderFlexItem> get items =>
|
||||
UnmodifiableListView(_columnDatas);
|
||||
|
||||
@override
|
||||
bool removePhantom(String columnId) {
|
||||
final columnController = this.columnController(columnId);
|
||||
final index = columnController.items.indexWhere((item) => item.isPhantom);
|
||||
|
||||
final isExist = index != -1;
|
||||
if (isExist) {
|
||||
columnController.removeAt(index);
|
||||
|
||||
Log.debug(
|
||||
'[$BoardPhantomController] Column$columnId remove phantom, current count: ${columnController.items.length}');
|
||||
}
|
||||
return isExist;
|
||||
}
|
||||
|
||||
@override
|
||||
void updatePhantom(String columnId, int newIndex) {
|
||||
final columnDataController = columnController(columnId);
|
||||
final index =
|
||||
columnDataController.items.indexWhere((item) => item.isPhantom);
|
||||
|
||||
assert(index != -1);
|
||||
if (index != -1) {
|
||||
if (index != newIndex) {
|
||||
// Log.debug('[$BoardPhantomController] update $toColumnId:$index to $toColumnId:$phantomIndex');
|
||||
final item = columnDataController.removeAt(index, notify: false);
|
||||
columnDataController.insert(newIndex, item, notify: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void insertPhantom(String columnId, int index, PhantomColumnItem item) {
|
||||
columnController(columnId).insert(index, item);
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class ReorderDragTarget<T extends DragTargetData> extends StatefulWidget {
|
||||
|
||||
class _ReorderDragTargetState<T extends DragTargetData>
|
||||
extends State<ReorderDragTarget<T>> {
|
||||
/// Return the dragTarget's size
|
||||
/// Returns the dragTarget's size
|
||||
Size? _draggingFeedbackSize = Size.zero;
|
||||
|
||||
@override
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'dart:collection';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
@ -18,10 +19,11 @@ typedef OnReveivePassedInPhantom = void Function(
|
||||
|
||||
abstract class ReoderFlextDataSource {
|
||||
String get identifier;
|
||||
List<ReoderFlexItem> get items;
|
||||
UnmodifiableListView<ReoderFlexItem> get items;
|
||||
}
|
||||
|
||||
abstract class ReoderFlexItem {
|
||||
/// [id] is used to identify the item
|
||||
String get id;
|
||||
}
|
||||
|
||||
@ -30,7 +32,9 @@ class ReorderFlexConfig {
|
||||
final double draggingWidgetOpacity = 0.2;
|
||||
final Duration reorderAnimationDuration = const Duration(milliseconds: 250);
|
||||
final Duration scrollAnimationDuration = const Duration(milliseconds: 250);
|
||||
const ReorderFlexConfig();
|
||||
|
||||
final double? spacing;
|
||||
const ReorderFlexConfig({this.spacing});
|
||||
}
|
||||
|
||||
class ReorderFlex extends StatefulWidget {
|
||||
@ -38,7 +42,6 @@ class ReorderFlex extends StatefulWidget {
|
||||
|
||||
final List<Widget> children;
|
||||
final EdgeInsets? padding;
|
||||
final double? spacing;
|
||||
final Axis direction;
|
||||
final MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start;
|
||||
final ScrollController? scrollController;
|
||||
@ -62,7 +65,6 @@ class ReorderFlex extends StatefulWidget {
|
||||
this.onDragEnded,
|
||||
this.interceptor,
|
||||
this.padding,
|
||||
this.spacing,
|
||||
this.direction = Axis.vertical,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -132,8 +134,8 @@ class ReorderFlexState extends State<ReorderFlex>
|
||||
for (int i = 0; i < widget.children.length; i += 1) {
|
||||
Widget child = widget.children[i];
|
||||
|
||||
if (widget.spacing != null) {
|
||||
children.add(SizedBox(width: widget.spacing!));
|
||||
if (widget.config.spacing != null) {
|
||||
children.add(SizedBox(width: widget.config.spacing!));
|
||||
}
|
||||
|
||||
final wrapChild = _wrap(child, i);
|
||||
@ -203,7 +205,7 @@ class ReorderFlexState extends State<ReorderFlex>
|
||||
dragSpace = SizedBox.fromSize(size: dragState.dropAreaSize);
|
||||
}
|
||||
|
||||
/// Return the dragTarget it is not start dragging. The size of the
|
||||
/// Returns the dragTarget it is not start dragging. The size of the
|
||||
/// dragTarget is the same as the the passed in child.
|
||||
///
|
||||
if (dragState.isNotDragging()) {
|
||||
|
@ -8,24 +8,39 @@ import 'phantom_state.dart';
|
||||
|
||||
abstract class BoardPhantomControllerDelegate {
|
||||
BoardColumnDataController? controller(String columnId);
|
||||
}
|
||||
|
||||
mixin ColumnDataPhantomMixim {
|
||||
BoardColumnDataController? get;
|
||||
bool removePhantom(String columnId);
|
||||
|
||||
/// Insert the phantom into column
|
||||
///
|
||||
/// * [toColumnId] id of the column
|
||||
/// * [phantomIndex] the phantom occupies index
|
||||
void insertPhantom(
|
||||
String columnId,
|
||||
int index,
|
||||
PhantomColumnItem item,
|
||||
);
|
||||
|
||||
/// Update the column's phantom index if it exists.
|
||||
/// [toColumnId] the id of the column
|
||||
/// [dragTargetIndex] the index of the dragTarget
|
||||
void updatePhantom(String columnId, int newIndex);
|
||||
|
||||
void swapColumnItem(
|
||||
String fromColumnId,
|
||||
int fromColumnIndex,
|
||||
String toColumnId,
|
||||
int toColumnIndex,
|
||||
);
|
||||
}
|
||||
|
||||
class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate
|
||||
with CrossReorderFlexDragTargetDelegate {
|
||||
final BoardPhantomControllerDelegate delegate;
|
||||
|
||||
PhantomRecord? phantomRecord;
|
||||
|
||||
final BoardPhantomControllerDelegate delegate;
|
||||
final columnsState = ColumnPhantomStateController();
|
||||
|
||||
BoardPhantomController({required this.delegate});
|
||||
|
||||
bool get hasPhantom => phantomRecord != null;
|
||||
|
||||
bool isFromColumn(String columnId) {
|
||||
if (phantomRecord != null) {
|
||||
return phantomRecord!.fromColumnId == columnId;
|
||||
@ -64,67 +79,25 @@ class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate
|
||||
if (columnsState.isDragging(phantomRecord!.fromColumnId) == false) {
|
||||
return;
|
||||
}
|
||||
final item = delegate
|
||||
.controller(phantomRecord!.fromColumnId)
|
||||
?.removeAt(phantomRecord!.fromColumnIndex);
|
||||
assert(item != null);
|
||||
assert(delegate
|
||||
.controller(phantomRecord!.toColumnId)
|
||||
?.items[phantomRecord!.toColumnIndex] is PhantomColumnItem);
|
||||
delegate
|
||||
.controller(phantomRecord!.toColumnId)
|
||||
?.replace(phantomRecord!.toColumnIndex, item!);
|
||||
delegate.swapColumnItem(
|
||||
phantomRecord!.fromColumnId,
|
||||
phantomRecord!.fromColumnIndex,
|
||||
phantomRecord!.toColumnId,
|
||||
phantomRecord!.toColumnIndex,
|
||||
);
|
||||
|
||||
Log.debug("[$BoardPhantomController] did move ${phantomRecord.toString()}");
|
||||
phantomRecord = null;
|
||||
}
|
||||
|
||||
/// Update the column's phantom index if it exists.
|
||||
/// [toColumnId] the id of the column
|
||||
/// [dragTargetIndex] the index of the dragTarget
|
||||
void _updatePhantom(
|
||||
String toColumnId,
|
||||
int dragTargetIndex,
|
||||
) {
|
||||
final columnDataController = delegate.controller(toColumnId);
|
||||
final index =
|
||||
columnDataController?.items.indexWhere((item) => item.isPhantom);
|
||||
if (index == null) return;
|
||||
|
||||
assert(index != -1);
|
||||
if (index != -1) {
|
||||
if (index != dragTargetIndex) {
|
||||
// Log.debug('[$BoardPhantomController] update $toColumnId:$index to $toColumnId:$phantomIndex');
|
||||
final item = columnDataController!.removeAt(index, notify: false);
|
||||
columnDataController.insert(dragTargetIndex, item, notify: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the phantom in the column if it contains phantom
|
||||
void _removePhantom(String columnId) {
|
||||
final index = delegate
|
||||
.controller(columnId)
|
||||
?.items
|
||||
.indexWhere((item) => item.isPhantom);
|
||||
|
||||
if (index == null) return;
|
||||
|
||||
assert(index != -1);
|
||||
|
||||
if (index != -1) {
|
||||
delegate.controller(columnId)?.removeAt(index);
|
||||
Log.debug(
|
||||
'[$BoardPhantomController] Column$columnId remove phantom, current count: ${delegate.controller(columnId)?.items.length}');
|
||||
if (delegate.removePhantom(columnId)) {
|
||||
columnsState.notifyDidRemovePhantom(columnId);
|
||||
columnsState.removeColumnListener(columnId);
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert the phantom into column
|
||||
///
|
||||
/// * [toColumnId] id of the column
|
||||
/// * [phantomIndex] the phantom occupies index
|
||||
void _insertPhantom(
|
||||
String toColumnId,
|
||||
FlexDragTargetData dragTargetData,
|
||||
@ -135,9 +108,12 @@ class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate
|
||||
dragTargetData: dragTargetData,
|
||||
);
|
||||
columnsState.addColumnListener(toColumnId, phantomContext);
|
||||
delegate
|
||||
.controller(toColumnId)
|
||||
?.insert(phantomIndex, PhantomColumnItem(phantomContext));
|
||||
|
||||
delegate.insertPhantom(
|
||||
toColumnId,
|
||||
phantomIndex,
|
||||
PhantomColumnItem(phantomContext),
|
||||
);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
@ -204,7 +180,7 @@ class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate
|
||||
assert(phantomRecord != null);
|
||||
if (phantomRecord!.toColumnId == reorderFlexId) {
|
||||
/// Update the existing phantom index
|
||||
_updatePhantom(phantomRecord!.toColumnId, dragTargetIndex);
|
||||
delegate.updatePhantom(phantomRecord!.toColumnId, dragTargetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,6 +259,11 @@ class PhantomColumnItem extends ColumnItem {
|
||||
Widget get draggingWidget => phantomContext.draggingWidget == null
|
||||
? const SizedBox()
|
||||
: phantomContext.draggingWidget!;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'phantom:$id';
|
||||
}
|
||||
}
|
||||
|
||||
class PassthroughPhantomContext extends FakeDragTargetEventTrigger
|
||||
|
Loading…
Reference in New Issue
Block a user