mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: improve grid focus and hover event handling (#1735)
* chore: improve primary cell accessory behavior * fix: focus border disappearing * chore: port to GridCellState * chore: fix typo * chore: connect popover controller * chore: final
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_bloc.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_bloc.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_cell.dart';
|
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_progress_bar.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
@ -29,7 +29,10 @@ class _BoardChecklistCellState extends State<BoardChecklistCell> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider.value(
|
return BlocProvider.value(
|
||||||
value: _cellBloc,
|
value: _cellBloc,
|
||||||
child: const ChecklistProgressBar(),
|
child: BlocBuilder<ChecklistCellBloc, ChecklistCellState>(
|
||||||
|
builder: (context, state) =>
|
||||||
|
ChecklistProgressBar(percent: state.percent),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,9 +67,6 @@ class _PrimaryCellAccessoryState extends State<PrimaryCellAccessory>
|
|||||||
with GridCellAccessoryState {
|
with GridCellAccessoryState {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (widget.isCellEditing) {
|
|
||||||
return const SizedBox();
|
|
||||||
} else {
|
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
message: LocaleKeys.tooltip_openAsPage.tr(),
|
message: LocaleKeys.tooltip_openAsPage.tr(),
|
||||||
textStyle: AFThemeExtension.of(context).caption.textColor(Colors.white),
|
textStyle: AFThemeExtension.of(context).caption.textColor(Colors.white),
|
||||||
@ -79,7 +76,6 @@ class _PrimaryCellAccessoryState extends State<PrimaryCellAccessory>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onTap() => widget.onTapCallback();
|
void onTap() => widget.onTapCallback();
|
||||||
|
@ -12,20 +12,23 @@ class CellContainer extends StatelessWidget {
|
|||||||
final GridCellWidget child;
|
final GridCellWidget child;
|
||||||
final AccessoryBuilder? accessoryBuilder;
|
final AccessoryBuilder? accessoryBuilder;
|
||||||
final double width;
|
final double width;
|
||||||
final RegionStateNotifier rowStateNotifier;
|
final bool isPrimary;
|
||||||
|
final CellContainerNotifier cellContainerNotifier;
|
||||||
|
|
||||||
const CellContainer({
|
const CellContainer({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.child,
|
required this.child,
|
||||||
required this.width,
|
required this.width,
|
||||||
required this.rowStateNotifier,
|
required this.isPrimary,
|
||||||
|
required this.cellContainerNotifier,
|
||||||
this.accessoryBuilder,
|
this.accessoryBuilder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ChangeNotifierProvider<_CellContainerNotifier>(
|
return ChangeNotifierProvider.value(
|
||||||
create: (_) => _CellContainerNotifier(child),
|
value: cellContainerNotifier,
|
||||||
child: Selector<_CellContainerNotifier, bool>(
|
child: Selector<CellContainerNotifier, bool>(
|
||||||
selector: (context, notifier) => notifier.isFocus,
|
selector: (context, notifier) => notifier.isFocus,
|
||||||
builder: (privderContext, isFocus, _) {
|
builder: (privderContext, isFocus, _) {
|
||||||
Widget container = Center(child: GridCellShortcuts(child: child));
|
Widget container = Center(child: GridCellShortcuts(child: child));
|
||||||
@ -41,6 +44,7 @@ class CellContainer extends StatelessWidget {
|
|||||||
if (accessories.isNotEmpty) {
|
if (accessories.isNotEmpty) {
|
||||||
container = _GridCellEnterRegion(
|
container = _GridCellEnterRegion(
|
||||||
accessories: accessories,
|
accessories: accessories,
|
||||||
|
isPrimary: isPrimary,
|
||||||
child: container,
|
child: container,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -81,17 +85,23 @@ class CellContainer extends StatelessWidget {
|
|||||||
class _GridCellEnterRegion extends StatelessWidget {
|
class _GridCellEnterRegion extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final List<GridCellAccessoryBuilder> accessories;
|
final List<GridCellAccessoryBuilder> accessories;
|
||||||
const _GridCellEnterRegion(
|
final bool isPrimary;
|
||||||
{required this.child, required this.accessories, Key? key})
|
const _GridCellEnterRegion({
|
||||||
: super(key: key);
|
required this.child,
|
||||||
|
required this.accessories,
|
||||||
|
required this.isPrimary,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Selector2<RegionStateNotifier, _CellContainerNotifier, bool>(
|
return Selector2<RegionStateNotifier, CellContainerNotifier, bool>(
|
||||||
selector: (context, regionNotifier, cellNotifier) => !cellNotifier.isFocus && (cellNotifier.onEnter),
|
selector: (context, regionNotifier, cellNotifier) =>
|
||||||
builder: (context, onEnter, _) {
|
!cellNotifier.isFocus &&
|
||||||
|
(cellNotifier.onEnter || regionNotifier.onEnter && isPrimary),
|
||||||
|
builder: (context, showAccessory, _) {
|
||||||
List<Widget> children = [child];
|
List<Widget> children = [child];
|
||||||
if (onEnter) {
|
if (showAccessory) {
|
||||||
children.add(
|
children.add(
|
||||||
CellAccessoryContainer(accessories: accessories).positioned(
|
CellAccessoryContainer(accessories: accessories).positioned(
|
||||||
right: GridSize.cellContentInsets.right,
|
right: GridSize.cellContentInsets.right,
|
||||||
@ -102,10 +112,10 @@ class _GridCellEnterRegion extends StatelessWidget {
|
|||||||
return MouseRegion(
|
return MouseRegion(
|
||||||
cursor: SystemMouseCursors.click,
|
cursor: SystemMouseCursors.click,
|
||||||
onEnter: (p) =>
|
onEnter: (p) =>
|
||||||
Provider.of<_CellContainerNotifier>(context, listen: false)
|
Provider.of<CellContainerNotifier>(context, listen: false)
|
||||||
.onEnter = true,
|
.onEnter = true,
|
||||||
onExit: (p) =>
|
onExit: (p) =>
|
||||||
Provider.of<_CellContainerNotifier>(context, listen: false)
|
Provider.of<CellContainerNotifier>(context, listen: false)
|
||||||
.onEnter = false,
|
.onEnter = false,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: AlignmentDirectional.center,
|
alignment: AlignmentDirectional.center,
|
||||||
@ -118,13 +128,13 @@ class _GridCellEnterRegion extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CellContainerNotifier extends ChangeNotifier {
|
class CellContainerNotifier extends ChangeNotifier {
|
||||||
final CellEditable cellEditable;
|
final CellEditable cellEditable;
|
||||||
VoidCallback? _onCellFocusListener;
|
VoidCallback? _onCellFocusListener;
|
||||||
bool _isFocus = false;
|
bool _isFocus = false;
|
||||||
bool _onEnter = false;
|
bool _onEnter = false;
|
||||||
|
|
||||||
_CellContainerNotifier(this.cellEditable) {
|
CellContainerNotifier(this.cellEditable) {
|
||||||
_onCellFocusListener = () => isFocus = cellEditable.onCellFocus.value;
|
_onCellFocusListener = () => isFocus = cellEditable.onCellFocus.value;
|
||||||
cellEditable.onCellFocus.addListener(_onCellFocusListener!);
|
cellEditable.onCellFocus.addListener(_onCellFocusListener!);
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,10 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
|||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../cell_builder.dart';
|
import '../cell_builder.dart';
|
||||||
import 'checklist_cell_editor.dart';
|
import 'checklist_cell_editor.dart';
|
||||||
import 'checklist_prograss_bar.dart';
|
import 'checklist_progress_bar.dart';
|
||||||
|
|
||||||
class GridChecklistCell extends GridCellWidget {
|
class GridChecklistCell extends GridCellWidget {
|
||||||
final GridCellControllerBuilder cellControllerBuilder;
|
final GridCellControllerBuilder cellControllerBuilder;
|
||||||
@ -15,12 +16,12 @@ class GridChecklistCell extends GridCellWidget {
|
|||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
GridChecklistCellState createState() => GridChecklistCellState();
|
GridCellState<GridChecklistCell> createState() => GridChecklistCellState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridChecklistCellState extends State<GridChecklistCell> {
|
class GridChecklistCellState extends GridCellState<GridChecklistCell> {
|
||||||
late PopoverController _popover;
|
|
||||||
late ChecklistCellBloc _cellBloc;
|
late ChecklistCellBloc _cellBloc;
|
||||||
|
late final PopoverController _popover;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -36,19 +37,7 @@ class GridChecklistCellState extends State<GridChecklistCell> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider.value(
|
return BlocProvider.value(
|
||||||
value: _cellBloc,
|
value: _cellBloc,
|
||||||
child: Stack(
|
child: AppFlowyPopover(
|
||||||
alignment: AlignmentDirectional.center,
|
|
||||||
fit: StackFit.expand,
|
|
||||||
children: [
|
|
||||||
_wrapPopover(const ChecklistProgressBar()),
|
|
||||||
InkWell(onTap: () => _popover.show()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _wrapPopover(Widget child) {
|
|
||||||
return AppFlowyPopover(
|
|
||||||
controller: _popover,
|
controller: _popover,
|
||||||
constraints: BoxConstraints.loose(const Size(260, 400)),
|
constraints: BoxConstraints.loose(const Size(260, 400)),
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
@ -65,23 +54,15 @@ class GridChecklistCellState extends State<GridChecklistCell> {
|
|||||||
onClose: () => widget.onCellEditing.value = false,
|
onClose: () => widget.onCellEditing.value = false,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: GridSize.cellContentInsets,
|
padding: GridSize.cellContentInsets,
|
||||||
child: child,
|
child: BlocBuilder<ChecklistCellBloc, ChecklistCellState>(
|
||||||
|
builder: (context, state) =>
|
||||||
|
ChecklistProgressBar(percent: state.percent),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class ChecklistProgressBar extends StatelessWidget {
|
|
||||||
const ChecklistProgressBar({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
void requestBeginFocus() => _popover.show();
|
||||||
return BlocBuilder<ChecklistCellBloc, ChecklistCellState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return ChecklistPrograssBar(
|
|
||||||
percent: state.percent,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_editor_bloc.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_editor_bloc.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
|
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_prograss_bar.dart';
|
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_progress_bar.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart';
|
import 'package:app_flowy/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
@ -48,7 +48,7 @@ class _GridChecklistCellEditorState extends State<GridChecklistCellEditor> {
|
|||||||
child: BlocBuilder<ChecklistCellEditorBloc, ChecklistCellEditorState>(
|
child: BlocBuilder<ChecklistCellEditorBloc, ChecklistCellEditorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final List<Widget> slivers = [
|
final List<Widget> slivers = [
|
||||||
const SliverChecklistPrograssBar(),
|
const SliverChecklistProgressBar(),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: GridSize.typeOptionContentInsets,
|
padding: GridSize.typeOptionContentInsets,
|
||||||
|
@ -8,9 +8,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:percent_indicator/percent_indicator.dart';
|
import 'package:percent_indicator/percent_indicator.dart';
|
||||||
|
|
||||||
class ChecklistPrograssBar extends StatelessWidget {
|
class ChecklistProgressBar extends StatelessWidget {
|
||||||
final double percent;
|
final double percent;
|
||||||
const ChecklistPrograssBar({required this.percent, Key? key})
|
const ChecklistProgressBar({required this.percent, Key? key})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -26,21 +26,21 @@ class ChecklistPrograssBar extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SliverChecklistPrograssBar extends StatelessWidget {
|
class SliverChecklistProgressBar extends StatelessWidget {
|
||||||
const SliverChecklistPrograssBar({Key? key}) : super(key: key);
|
const SliverChecklistProgressBar({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SliverPersistentHeader(
|
return SliverPersistentHeader(
|
||||||
pinned: true,
|
pinned: true,
|
||||||
delegate: _SliverChecklistPrograssBarDelegate(),
|
delegate: _SliverChecklistProgressBarDelegate(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SliverChecklistPrograssBarDelegate
|
class _SliverChecklistProgressBarDelegate
|
||||||
extends SliverPersistentHeaderDelegate {
|
extends SliverPersistentHeaderDelegate {
|
||||||
_SliverChecklistPrograssBarDelegate();
|
_SliverChecklistProgressBarDelegate();
|
||||||
|
|
||||||
double fixHeight = 60;
|
double fixHeight = 60;
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ class _SliverChecklistPrograssBarDelegate
|
|||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 6.0),
|
padding: const EdgeInsets.only(top: 6.0),
|
||||||
child: ChecklistPrograssBar(percent: state.percent),
|
child: ChecklistProgressBar(percent: state.percent),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
@ -39,11 +39,12 @@ class GridSingleSelectCell extends GridCellWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GridSingleSelectCell> createState() => _SingleSelectCellState();
|
GridCellState<GridSingleSelectCell> createState() => _SingleSelectCellState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SingleSelectCellState extends State<GridSingleSelectCell> {
|
class _SingleSelectCellState extends GridCellState<GridSingleSelectCell> {
|
||||||
late SelectOptionCellBloc _cellBloc;
|
late SelectOptionCellBloc _cellBloc;
|
||||||
|
late final PopoverController _popover;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -51,6 +52,7 @@ class _SingleSelectCellState extends State<GridSingleSelectCell> {
|
|||||||
widget.cellControllerBuilder.build() as GridSelectOptionCellController;
|
widget.cellControllerBuilder.build() as GridSelectOptionCellController;
|
||||||
_cellBloc = getIt<SelectOptionCellBloc>(param1: cellController)
|
_cellBloc = getIt<SelectOptionCellBloc>(param1: cellController)
|
||||||
..add(const SelectOptionCellEvent.initial());
|
..add(const SelectOptionCellEvent.initial());
|
||||||
|
_popover = PopoverController();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +65,10 @@ class _SingleSelectCellState extends State<GridSingleSelectCell> {
|
|||||||
return SelectOptionWrap(
|
return SelectOptionWrap(
|
||||||
selectOptions: state.selectedOptions,
|
selectOptions: state.selectedOptions,
|
||||||
cellStyle: widget.cellStyle,
|
cellStyle: widget.cellStyle,
|
||||||
onFocus: (value) => widget.onCellEditing.value = value,
|
onCellEditing: widget.onCellEditing,
|
||||||
cellControllerBuilder: widget.cellControllerBuilder);
|
popoverController: _popover,
|
||||||
|
cellControllerBuilder: widget.cellControllerBuilder,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -75,6 +79,9 @@ class _SingleSelectCellState extends State<GridSingleSelectCell> {
|
|||||||
_cellBloc.close();
|
_cellBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void requestBeginFocus() => _popover.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -95,11 +102,12 @@ class GridMultiSelectCell extends GridCellWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GridMultiSelectCell> createState() => _MultiSelectCellState();
|
GridCellState<GridMultiSelectCell> createState() => _MultiSelectCellState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MultiSelectCellState extends State<GridMultiSelectCell> {
|
class _MultiSelectCellState extends GridCellState<GridMultiSelectCell> {
|
||||||
late SelectOptionCellBloc _cellBloc;
|
late SelectOptionCellBloc _cellBloc;
|
||||||
|
late final PopoverController _popover;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -107,6 +115,7 @@ class _MultiSelectCellState extends State<GridMultiSelectCell> {
|
|||||||
widget.cellControllerBuilder.build() as GridSelectOptionCellController;
|
widget.cellControllerBuilder.build() as GridSelectOptionCellController;
|
||||||
_cellBloc = getIt<SelectOptionCellBloc>(param1: cellController)
|
_cellBloc = getIt<SelectOptionCellBloc>(param1: cellController)
|
||||||
..add(const SelectOptionCellEvent.initial());
|
..add(const SelectOptionCellEvent.initial());
|
||||||
|
_popover = PopoverController();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +128,8 @@ class _MultiSelectCellState extends State<GridMultiSelectCell> {
|
|||||||
return SelectOptionWrap(
|
return SelectOptionWrap(
|
||||||
selectOptions: state.selectedOptions,
|
selectOptions: state.selectedOptions,
|
||||||
cellStyle: widget.cellStyle,
|
cellStyle: widget.cellStyle,
|
||||||
onFocus: (value) => widget.onCellEditing.value = value,
|
onCellEditing: widget.onCellEditing,
|
||||||
|
popoverController: _popover,
|
||||||
cellControllerBuilder: widget.cellControllerBuilder,
|
cellControllerBuilder: widget.cellControllerBuilder,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -132,17 +142,23 @@ class _MultiSelectCellState extends State<GridMultiSelectCell> {
|
|||||||
_cellBloc.close();
|
_cellBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void requestBeginFocus() => _popover.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SelectOptionWrap extends StatefulWidget {
|
class SelectOptionWrap extends StatefulWidget {
|
||||||
final List<SelectOptionPB> selectOptions;
|
final List<SelectOptionPB> selectOptions;
|
||||||
final void Function(bool)? onFocus;
|
|
||||||
final SelectOptionCellStyle? cellStyle;
|
final SelectOptionCellStyle? cellStyle;
|
||||||
final GridCellControllerBuilder cellControllerBuilder;
|
final GridCellControllerBuilder cellControllerBuilder;
|
||||||
|
final PopoverController popoverController;
|
||||||
|
final ValueNotifier onCellEditing;
|
||||||
|
|
||||||
const SelectOptionWrap({
|
const SelectOptionWrap({
|
||||||
required this.selectOptions,
|
required this.selectOptions,
|
||||||
required this.cellControllerBuilder,
|
required this.cellControllerBuilder,
|
||||||
this.onFocus,
|
required this.onCellEditing,
|
||||||
|
required this.popoverController,
|
||||||
this.cellStyle,
|
this.cellStyle,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -152,48 +168,29 @@ class SelectOptionWrap extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SelectOptionWrapState extends State<SelectOptionWrap> {
|
class _SelectOptionWrapState extends State<SelectOptionWrap> {
|
||||||
late PopoverController _popover;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
_popover = PopoverController();
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Widget child = _buildOptions(context);
|
Widget child = _buildOptions(context);
|
||||||
|
|
||||||
return Stack(
|
|
||||||
alignment: AlignmentDirectional.center,
|
|
||||||
fit: StackFit.expand,
|
|
||||||
children: [
|
|
||||||
_wrapPopover(child),
|
|
||||||
InkWell(onTap: () => _popover.show()),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _wrapPopover(Widget child) {
|
|
||||||
final constraints = BoxConstraints.loose(Size(
|
final constraints = BoxConstraints.loose(Size(
|
||||||
SelectOptionCellEditor.editorPanelWidth,
|
SelectOptionCellEditor.editorPanelWidth,
|
||||||
300,
|
300,
|
||||||
));
|
));
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
controller: _popover,
|
controller: widget.popoverController,
|
||||||
constraints: constraints,
|
constraints: constraints,
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
popupBuilder: (BuildContext context) {
|
popupBuilder: (BuildContext context) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
widget.onFocus?.call(true);
|
widget.onCellEditing.value = true;
|
||||||
});
|
});
|
||||||
return SelectOptionCellEditor(
|
return SelectOptionCellEditor(
|
||||||
cellController: widget.cellControllerBuilder.build()
|
cellController: widget.cellControllerBuilder.build()
|
||||||
as GridSelectOptionCellController,
|
as GridSelectOptionCellController,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onClose: () => widget.onFocus?.call(false),
|
onClose: () => widget.onCellEditing.value = false,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: GridSize.cellContentInsets,
|
padding: GridSize.cellContentInsets,
|
||||||
child: child,
|
child: child,
|
||||||
|
@ -225,8 +225,8 @@ class RowContent extends StatelessWidget {
|
|||||||
|
|
||||||
return CellContainer(
|
return CellContainer(
|
||||||
width: cellId.fieldInfo.width.toDouble(),
|
width: cellId.fieldInfo.width.toDouble(),
|
||||||
rowStateNotifier:
|
isPrimary: cellId.fieldInfo.isPrimary,
|
||||||
Provider.of<RegionStateNotifier>(context, listen: false),
|
cellContainerNotifier: CellContainerNotifier(child),
|
||||||
accessoryBuilder: (buildContext) {
|
accessoryBuilder: (buildContext) {
|
||||||
final builder = child.accessoryBuilder;
|
final builder = child.accessoryBuilder;
|
||||||
List<GridCellAccessoryBuilder> accessories = [];
|
List<GridCellAccessoryBuilder> accessories = [];
|
||||||
|
Reference in New Issue
Block a user