From 6aaf5dc171a0e72ffdca1b817b6f9e6c165fffb6 Mon Sep 17 00:00:00 2001 From: Freek van de Ven Date: Fri, 18 Nov 2022 14:22:05 +0100 Subject: [PATCH] feat: add table size option --- example/lib/main.dart | 76 ++++++++-------- lib/src/timetable.dart | 175 +++++++++++++++++++------------------ lib/src/widgets/table.dart | 16 +++- 3 files changed, 144 insertions(+), 123 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 150abff..8ee9e82 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -121,45 +121,49 @@ class _TimetableDemoState extends State { @override Widget build(BuildContext context) { + var size = MediaQuery.of(context).size; return Scaffold( + // backgroundColor: Colors.green, body: Padding( padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), - child: SingleChildScrollView( - child: Column( - children: [ - // toggle between horizontal and vertical - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - TextButton( - onPressed: () { - setState(() { - _horizontal = !_horizontal; - }); - }, - child: Text(_horizontal ? 'Horizontal' : 'Vertical'), - ), - ], - ), - // toggle between grouped and ungrouped blocks - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text('Grouped'), - Switch( - value: _grouped, - onChanged: (value) { - setState(() { - _grouped = value; - }); - }, - ), - ], - ), - Timetable( + child: Column( + children: [ + // toggle between horizontal and vertical + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + onPressed: () { + setState(() { + _horizontal = !_horizontal; + }); + }, + child: Text(_horizontal ? 'Horizontal' : 'Vertical'), + ), + ], + ), + // toggle between grouped and ungrouped blocks + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text('Grouped'), + Switch( + value: _grouped, + onChanged: (value) { + setState(() { + _grouped = value; + }); + }, + ), + ], + ), + Container( + color: Colors.white, + child: Timetable( + size: Size(size.width, size.height * 0.64), tableDirection: _horizontal ? Axis.horizontal : Axis.vertical, startHour: 3, - endHour: 22, + endHour: 24, timeBlocks: blocks, scrollController: _scrollController, combineBlocks: true, @@ -169,8 +173,8 @@ class _TimetableDemoState extends State { blockPaddingBetween: 10, ), ), - ], - ), + ), + ], ), ), ); diff --git a/lib/src/timetable.dart b/lib/src/timetable.dart index 250ae5b..b94f42a 100644 --- a/lib/src/timetable.dart +++ b/lib/src/timetable.dart @@ -21,6 +21,7 @@ class Timetable extends StatefulWidget { const Timetable({ this.tableDirection = Axis.vertical, this.timeBlocks = const [], + this.size, this.scrollController, this.scrollPhysics, this.startHour = 0, @@ -37,6 +38,9 @@ class Timetable extends StatefulWidget { /// The Axis in which the table is layed out. final Axis tableDirection; + /// The [Size] of the timetable. + final Size? size; + /// Hour at which the timetable starts. final int startHour; @@ -106,81 +110,44 @@ class _TimetableState extends State { blocks = widget.timeBlocks; } var linePadding = _calculateTableTextSize().width; - return SingleChildScrollView( - key: // TODO(freek): test if this is necessary - ValueKey(widget.timeBlocks.length), - physics: widget.scrollPhysics ?? const BouncingScrollPhysics(), - controller: _scrollController, - scrollDirection: widget.tableDirection, - child: Stack( - alignment: Alignment.topLeft, - children: [ - table.Table( - tableHeight: widget.tableDirection == Axis.horizontal - ? _calculateTableHeight() - : 0, - tableDirection: widget.tableDirection, - startHour: widget.startHour, - endHour: widget.endHour, - hourDimension: widget.hourDimension, - tableOffset: _calculateTableStart(widget.tableDirection).width, - theme: widget.theme, - ), - Container( - margin: EdgeInsets.only( - top: _calculateTableStart(widget.tableDirection).height, - left: _calculateTableStart(widget.tableDirection).width, + return SizedBox( + width: widget.size?.width, + height: widget.size?.height, + child: SingleChildScrollView( + physics: widget.scrollPhysics ?? const BouncingScrollPhysics(), + controller: _scrollController, + scrollDirection: widget.tableDirection, + child: Stack( + alignment: Alignment.topLeft, + children: [ + table.Table( + tableHeight: widget.tableDirection == Axis.horizontal + ? _calculateTableHeight() + : 0, + tableDirection: widget.tableDirection, + startHour: widget.startHour, + endHour: widget.endHour, + hourDimension: widget.hourDimension, + tableOffset: _calculateTableStart(widget.tableDirection).width, + theme: widget.theme, + size: widget.size, ), - child: SingleChildScrollView( - key: // TODO(freek): test if this is necessary - ValueKey(widget.timeBlocks.length), - physics: widget.scrollPhysics ?? const BouncingScrollPhysics(), - scrollDirection: widget.tableDirection == Axis.horizontal - ? Axis.vertical - : Axis.horizontal, - child: (widget.tableDirection == Axis.horizontal) - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - SizedBox(height: widget.theme.tableTextOffset), - if (widget.mergeBlocks || widget.combineBlocks) ...[ - for (var orderedBlocks in (widget.mergeBlocks) - ? mergeBlocksInColumns(blocks) - : groupBlocksById(blocks)) ...[ - Stack( - children: [ - for (var block in orderedBlocks) ...[ - _showBlock(block), - ], - ], - ), - SizedBox( - height: widget.theme.blockPaddingBetween, - ), - ], - ] else ...[ - for (var block in blocks) ...[ - _showBlock(block, linePadding: linePadding), - SizedBox( - height: widget.theme.blockPaddingBetween, - ), - ], - ], - // emtpy block at the end - SizedBox( - height: max( - widget.theme.tablePaddingEnd - - widget.theme.blockPaddingBetween, - 0, - ), - ), - ], - ) - : IntrinsicHeight( - child: Row( + Container( + margin: EdgeInsets.only( + top: _calculateTableStart(widget.tableDirection).height, + left: _calculateTableStart(widget.tableDirection).width, + ), + child: SingleChildScrollView( + physics: widget.scrollPhysics ?? const BouncingScrollPhysics(), + scrollDirection: widget.tableDirection == Axis.horizontal + ? Axis.vertical + : Axis.horizontal, + child: (widget.tableDirection == Axis.horizontal) + ? Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, children: [ + SizedBox(height: widget.theme.tableTextOffset), if (widget.mergeBlocks || widget.combineBlocks) ...[ for (var orderedBlocks in (widget.mergeBlocks) ? mergeBlocksInColumns(blocks) @@ -193,31 +160,69 @@ class _TimetableState extends State { ], ), SizedBox( - width: widget.theme.blockPaddingBetween, + height: widget.theme.blockPaddingBetween, ), ], ] else ...[ for (var block in blocks) ...[ - _showBlock(block), + _showBlock(block, linePadding: linePadding), + SizedBox( + height: widget.theme.blockPaddingBetween, + ), ], ], + // emtpy block at the end SizedBox( - width: max( + height: max( widget.theme.tablePaddingEnd - widget.theme.blockPaddingBetween, 0, ), - height: widget.hourDimension * - (widget.endHour - - widget.startHour + - 0.5), // empty halfhour at the end ), ], + ) + : IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.mergeBlocks || widget.combineBlocks) ...[ + for (var orderedBlocks in (widget.mergeBlocks) + ? mergeBlocksInColumns(blocks) + : groupBlocksById(blocks)) ...[ + Stack( + children: [ + for (var block in orderedBlocks) ...[ + _showBlock(block), + ], + ], + ), + SizedBox( + width: widget.theme.blockPaddingBetween, + ), + ], + ] else ...[ + for (var block in blocks) ...[ + _showBlock(block), + ], + ], + SizedBox( + width: max( + widget.theme.tablePaddingEnd - + widget.theme.blockPaddingBetween, + 0, + ), + height: widget.hourDimension * + (widget.endHour - + widget.startHour + + 0.5), // empty halfhour at the end + ), + ], + ), ), - ), + ), ), - ), - ], + ], + ), ), ); } @@ -225,11 +230,13 @@ class _TimetableState extends State { Size _calculateTableStart(Axis axis) { return Size( (axis == Axis.horizontal) - ? 0 + ? _calculateTableTextSize().width / 2 : _calculateTableTextSize().width + widget.theme.tablePaddingStart + widget.theme.tableTextOffset, - (axis == Axis.vertical) ? 0 : _calculateTableTextSize().height, + (axis == Axis.vertical) + ? _calculateTableTextSize().height / 2 + : _calculateTableTextSize().height, ); } diff --git a/lib/src/widgets/table.dart b/lib/src/widgets/table.dart index 026260e..0510516 100644 --- a/lib/src/widgets/table.dart +++ b/lib/src/widgets/table.dart @@ -10,6 +10,7 @@ class Table extends StatelessWidget { const Table({ required this.startHour, required this.endHour, + this.size, this.tableDirection = Axis.vertical, this.hourDimension = 80, this.tableOffset = 20, @@ -24,6 +25,9 @@ class Table extends StatelessWidget { /// The [Axis] in which the table is layed out. final Axis tableDirection; + /// The [Size] used for the table rendering. + final Size? size; + /// The hour the table starts at. final int startHour; @@ -64,7 +68,9 @@ class Table extends StatelessWidget { Container( color: theme.lineColor, width: theme.lineHeight, - height: tableHeight, + height: (size ?? MediaQuery.of(context).size).height - + textSize.dy - + theme.tableTextOffset, ), ], ), @@ -84,7 +90,11 @@ class Table extends StatelessWidget { // draw dotted line for (int i = 0; i < - tableHeight / + (((size ?? MediaQuery.of(context).size) + .height) - + textSize.dy - + theme.tableTextOffset - + theme.lineDashDistance) / ((theme.lineDashLength + theme.lineDashDistance) / 2); @@ -144,7 +154,7 @@ class Table extends StatelessWidget { children: [ for (int i = 0; i < - (MediaQuery.of(context).size.width - + ((size ?? MediaQuery.of(context).size).width - tableOffset - textSize.dx / 2) / ((theme.lineDashLength +