Skip to content

Commit

Permalink
fix(code style): use formatter and examples (#2)
Browse files Browse the repository at this point in the history
To please the flutter pub score,
use flutter format instead of flutter stylizer and
create a small example.

Signed-off-by: Christoph Bühler <christoph@smartive.ch>
  • Loading branch information
buehler authored Mar 9, 2023
1 parent ed9aa59 commit 8e32070
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 76 deletions.
13 changes: 0 additions & 13 deletions .flutter-stylizer.yml

This file was deleted.

1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
with:
channel: 'stable'
- run: flutter pub get
- run: dart format --fix --set-exit-if-changed .
- run: flutter analyze
- run: flutter test --coverage
- name: Setup LCOV
Expand Down
22 changes: 22 additions & 0 deletions example/example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
import 'package:generic_dropdown_widget/generic_dropdown_widget.dart';

class Dropdown extends StatelessWidget {
const Dropdown({super.key});

@override
Widget build(BuildContext context) => GenericDropdown(
openOnRender: false,
closeOnOutsideTap: true,
toggleBuilder: (context, isOpen) => Container(
height: 50,
width: 50,
color: isOpen ? Colors.green : Colors.red,
),
contentBuilder: (context, repaint, close) => Container(
height: 100,
width: 100,
color: Colors.blue,
),
);
}
98 changes: 68 additions & 30 deletions lib/src/generic_dropdown.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ enum DropdownDirection {
downRight,
}

typedef ContentBuilder = Widget Function(BuildContext context, VoidCallback repaint, VoidCallback close);
typedef ContentBuilder = Widget Function(
BuildContext context, VoidCallback repaint, VoidCallback close);
typedef ToggleBuilder = Widget Function(BuildContext context, bool isOpen);

/// A generic dropdown widget that enables arbitrary content
Expand Down Expand Up @@ -130,7 +131,10 @@ class _GenericDropdownState extends State<GenericDropdown> {
}

RenderBox? _ancestor(BuildContext context) =>
GenericDropdownConfigProvider.of(context)?.rootScreenKey?.currentContext?.findRenderObject() as RenderBox?;
GenericDropdownConfigProvider.of(context)
?.rootScreenKey
?.currentContext
?.findRenderObject() as RenderBox?;

void _close() {
_overlayEntry?.remove();
Expand All @@ -142,7 +146,8 @@ class _GenericDropdownState extends State<GenericDropdown> {
final renderBox = context.findRenderObject() as RenderBox;

final size = renderBox.size;
final togglePosition = renderBox.localToGlobal(Offset.zero, ancestor: _ancestor(context));
final togglePosition =
renderBox.localToGlobal(Offset.zero, ancestor: _ancestor(context));

final screenSize = _screenSize(context);

Expand All @@ -166,61 +171,93 @@ class _GenericDropdownState extends State<GenericDropdown> {
double? top, left, bottom, right;

// Anchor TOP LEFT
if (widget.anchor == DropdownAnchor.topLeft && widget.direction == DropdownDirection.upLeft) {
if (widget.anchor == DropdownAnchor.topLeft &&
widget.direction == DropdownDirection.upLeft) {
bottom = screenSize.height - togglePosition.dy + widget.offset.dy;
right = screenSize.width - togglePosition.dx + widget.offset.dx;
} else if (widget.anchor == DropdownAnchor.topLeft && widget.direction == DropdownDirection.upRight) {
} else if (widget.anchor == DropdownAnchor.topLeft &&
widget.direction == DropdownDirection.upRight) {
bottom = screenSize.height - togglePosition.dy + widget.offset.dy;
left = togglePosition.dx + widget.offset.dx;
} else if (widget.anchor == DropdownAnchor.topLeft && widget.direction == DropdownDirection.downLeft) {
} else if (widget.anchor == DropdownAnchor.topLeft &&
widget.direction == DropdownDirection.downLeft) {
top = togglePosition.dy + widget.offset.dy;
right = screenSize.width - togglePosition.dx + widget.offset.dx;
} else if (widget.anchor == DropdownAnchor.topLeft && widget.direction == DropdownDirection.downRight) {
} else if (widget.anchor == DropdownAnchor.topLeft &&
widget.direction == DropdownDirection.downRight) {
top = togglePosition.dy + widget.offset.dy;
left = togglePosition.dx + widget.offset.dx;
}

// Anchor TOP RIGHT
if (widget.anchor == DropdownAnchor.topRight && widget.direction == DropdownDirection.upLeft) {
if (widget.anchor == DropdownAnchor.topRight &&
widget.direction == DropdownDirection.upLeft) {
bottom = screenSize.height - togglePosition.dy + widget.offset.dy;
right = screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
} else if (widget.anchor == DropdownAnchor.topRight && widget.direction == DropdownDirection.upRight) {
right =
screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
} else if (widget.anchor == DropdownAnchor.topRight &&
widget.direction == DropdownDirection.upRight) {
bottom = screenSize.height - togglePosition.dy + widget.offset.dy;
left = togglePosition.dx + widget.offset.dx + size.width;
} else if (widget.anchor == DropdownAnchor.topRight && widget.direction == DropdownDirection.downLeft) {
} else if (widget.anchor == DropdownAnchor.topRight &&
widget.direction == DropdownDirection.downLeft) {
top = togglePosition.dy + widget.offset.dy;
right = screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
} else if (widget.anchor == DropdownAnchor.topRight && widget.direction == DropdownDirection.downRight) {
right =
screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
} else if (widget.anchor == DropdownAnchor.topRight &&
widget.direction == DropdownDirection.downRight) {
top = togglePosition.dy + widget.offset.dy;
left = togglePosition.dx + widget.offset.dx + size.width;
}

// Anchor BOTTOM LEFT
if (widget.anchor == DropdownAnchor.bottomLeft && widget.direction == DropdownDirection.upLeft) {
bottom = screenSize.height - togglePosition.dy + widget.offset.dy - size.height;
if (widget.anchor == DropdownAnchor.bottomLeft &&
widget.direction == DropdownDirection.upLeft) {
bottom = screenSize.height -
togglePosition.dy +
widget.offset.dy -
size.height;
right = screenSize.width - togglePosition.dx + widget.offset.dx;
} else if (widget.anchor == DropdownAnchor.bottomLeft && widget.direction == DropdownDirection.upRight) {
bottom = screenSize.height - togglePosition.dy + widget.offset.dy - size.height;
} else if (widget.anchor == DropdownAnchor.bottomLeft &&
widget.direction == DropdownDirection.upRight) {
bottom = screenSize.height -
togglePosition.dy +
widget.offset.dy -
size.height;
left = togglePosition.dx + widget.offset.dx;
} else if (widget.anchor == DropdownAnchor.bottomLeft && widget.direction == DropdownDirection.downLeft) {
} else if (widget.anchor == DropdownAnchor.bottomLeft &&
widget.direction == DropdownDirection.downLeft) {
top = togglePosition.dy + widget.offset.dy + size.height;
right = screenSize.width - togglePosition.dx + widget.offset.dx;
} else if (widget.anchor == DropdownAnchor.bottomLeft && widget.direction == DropdownDirection.downRight) {
} else if (widget.anchor == DropdownAnchor.bottomLeft &&
widget.direction == DropdownDirection.downRight) {
top = togglePosition.dy + widget.offset.dy + size.height;
left = togglePosition.dx + widget.offset.dx;
}

// Anchor BOTTOM RIGHT
if (widget.anchor == DropdownAnchor.bottomRight && widget.direction == DropdownDirection.upLeft) {
bottom = screenSize.height - togglePosition.dy + widget.offset.dy - size.height;
right = screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
} else if (widget.anchor == DropdownAnchor.bottomRight && widget.direction == DropdownDirection.upRight) {
bottom = screenSize.height - togglePosition.dy + widget.offset.dy - size.height;
if (widget.anchor == DropdownAnchor.bottomRight &&
widget.direction == DropdownDirection.upLeft) {
bottom = screenSize.height -
togglePosition.dy +
widget.offset.dy -
size.height;
right =
screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
} else if (widget.anchor == DropdownAnchor.bottomRight &&
widget.direction == DropdownDirection.upRight) {
bottom = screenSize.height -
togglePosition.dy +
widget.offset.dy -
size.height;
left = togglePosition.dx + widget.offset.dx + size.width;
} else if (widget.anchor == DropdownAnchor.bottomRight && widget.direction == DropdownDirection.downLeft) {
} else if (widget.anchor == DropdownAnchor.bottomRight &&
widget.direction == DropdownDirection.downLeft) {
top = togglePosition.dy + widget.offset.dy + size.height;
right = screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
} else if (widget.anchor == DropdownAnchor.bottomRight && widget.direction == DropdownDirection.downRight) {
right =
screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
} else if (widget.anchor == DropdownAnchor.bottomRight &&
widget.direction == DropdownDirection.downRight) {
top = togglePosition.dy + widget.offset.dy + size.height;
left = togglePosition.dx + widget.offset.dx + size.width;
}
Expand Down Expand Up @@ -249,8 +286,8 @@ class _GenericDropdownState extends State<GenericDropdown> {
// content.
},
child: StatefulBuilder(
builder: (context, setState) =>
widget.contentBuilder.call(context, () => setState(() {}), _close)),
builder: (context, setState) => widget.contentBuilder
.call(context, () => setState(() {}), _close)),
),
),
],
Expand All @@ -265,7 +302,8 @@ class _GenericDropdownState extends State<GenericDropdown> {
setState(() => _isOpen = true);
}

Size _screenSize(BuildContext context) => _ancestor(context)?.size ?? MediaQuery.of(context).size;
Size _screenSize(BuildContext context) =>
_ancestor(context)?.size ?? MediaQuery.of(context).size;

@override
Widget build(BuildContext context) => Row(
Expand Down
10 changes: 6 additions & 4 deletions lib/src/generic_dropdown_config_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ class GenericDropdownConfigProvider extends InheritedWidget {
/// of the content overlay to the toggle.
final GlobalKey? rootScreenKey;

const GenericDropdownConfigProvider({super.key, this.rootScreenKey, required super.child});
const GenericDropdownConfigProvider(
{super.key, this.rootScreenKey, required super.child});

@override
bool updateShouldNotify(GenericDropdownConfigProvider oldWidget) => rootScreenKey != oldWidget.rootScreenKey;
bool updateShouldNotify(GenericDropdownConfigProvider oldWidget) =>
rootScreenKey != oldWidget.rootScreenKey;

static GenericDropdownConfigProvider? of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<GenericDropdownConfigProvider>();
static GenericDropdownConfigProvider? of(BuildContext context) => context
.dependOnInheritedWidgetOfExactType<GenericDropdownConfigProvider>();
}
49 changes: 36 additions & 13 deletions storybook/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ void main() {
home: Scaffold(
body: SafeArea(
child: GenericDropdownConfigProvider(
rootScreenKey: rootKey, child: Center(key: UniqueKey(), child: child))))),
rootScreenKey: rootKey,
child: Center(key: UniqueKey(), child: child))))),
// initialStory: 'Generic Dropdown',
stories: [
_dropdown(),
Expand Down Expand Up @@ -73,26 +74,37 @@ Story _dropdown() => Story(
toggleBuilder: (context, isOpen) => Container(
height: 120,
width: 120,
color: isOpen ? Colors.amber.withOpacity(.25) : Colors.blue.withOpacity(.25),
color: isOpen
? Colors.amber.withOpacity(.25)
: Colors.blue.withOpacity(.25),
child: Text('Toggle (${isOpen ? 'Open' : 'Closed'})'),
),
offset: Offset(
context.knobs.sliderInt(label: 'X Offset', initial: 0, min: -100, max: 100).toDouble(),
context.knobs.sliderInt(label: 'Y Offset', initial: 0, min: -100, max: 100).toDouble(),
context.knobs
.sliderInt(label: 'X Offset', initial: 0, min: -100, max: 100)
.toDouble(),
context.knobs
.sliderInt(label: 'Y Offset', initial: 0, min: -100, max: 100)
.toDouble(),
),
anchor: context.knobs.options(
label: 'Anchor',
description: 'The anchor for the content dropdown.',
initial: DropdownAnchor.bottomLeft,
options: DropdownAnchor.values.map((v) => Option(label: v.name, value: v)).toList()),
options: DropdownAnchor.values
.map((v) => Option(label: v.name, value: v))
.toList()),
direction: context.knobs.options(
label: 'Direction',
description: 'The direction where the dropdown should open to.',
initial: DropdownDirection.downRight,
options: DropdownDirection.values.map((v) => Option(label: v.name, value: v)).toList()),
options: DropdownDirection.values
.map((v) => Option(label: v.name, value: v))
.toList()),
closeOnOutsideTap: context.knobs.boolean(
label: 'Close On Outside Tap',
description: 'Whether the content is closed on an outside tap or only if the content calls close().',
description:
'Whether the content is closed on an outside tap or only if the content calls close().',
initial: true),
));
});
Expand Down Expand Up @@ -142,26 +154,37 @@ Story _openDropdown() => Story(
toggleBuilder: (context, isOpen) => Container(
height: 120,
width: 120,
color: isOpen ? Colors.amber.withOpacity(.25) : Colors.blue.withOpacity(.25),
color: isOpen
? Colors.amber.withOpacity(.25)
: Colors.blue.withOpacity(.25),
child: Text('Toggle (${isOpen ? 'Open' : 'Closed'})'),
),
offset: Offset(
context.knobs.sliderInt(label: 'X Offset', initial: 0, min: -100, max: 100).toDouble(),
context.knobs.sliderInt(label: 'Y Offset', initial: 0, min: -100, max: 100).toDouble(),
context.knobs
.sliderInt(label: 'X Offset', initial: 0, min: -100, max: 100)
.toDouble(),
context.knobs
.sliderInt(label: 'Y Offset', initial: 0, min: -100, max: 100)
.toDouble(),
),
anchor: context.knobs.options(
label: 'Anchor',
description: 'The anchor for the content dropdown.',
initial: DropdownAnchor.bottomLeft,
options: DropdownAnchor.values.map((v) => Option(label: v.name, value: v)).toList()),
options: DropdownAnchor.values
.map((v) => Option(label: v.name, value: v))
.toList()),
direction: context.knobs.options(
label: 'Direction',
description: 'The direction where the dropdown should open to.',
initial: DropdownDirection.downRight,
options: DropdownDirection.values.map((v) => Option(label: v.name, value: v)).toList()),
options: DropdownDirection.values
.map((v) => Option(label: v.name, value: v))
.toList()),
closeOnOutsideTap: context.knobs.boolean(
label: 'Close On Outside Tap',
description: 'Whether the content is closed on an outside tap or only if the content calls close().',
description:
'Whether the content is closed on an outside tap or only if the content calls close().',
initial: true),
));
});
Loading

0 comments on commit 8e32070

Please sign in to comment.