diff --git a/lib/src/block.dart b/lib/src/block.dart index 509fa1a..f48d6a6 100644 --- a/lib/src/block.dart +++ b/lib/src/block.dart @@ -6,6 +6,8 @@ class Block extends StatelessWidget { required this.end, required this.startHour, required this.blockWidth, + required this.hourHeight, + this.blockColor = const Color(0x80FF0000), this.linePadding = 8, this.child, Key? key, @@ -23,9 +25,15 @@ class Block extends StatelessWidget { /// The start hour of the timetable. final int startHour; + /// The heigh of one hour in the timetable. + final double hourHeight; + /// The width of the block if there is no child final double blockWidth; + /// The color of the block if there is no child + final Color blockColor; + /// The padding between the lines and the numbers final double linePadding; @@ -33,7 +41,6 @@ class Block extends StatelessWidget { Widget build(BuildContext context) { return Container( margin: EdgeInsets.only( - left: 10, top: (((start.hour - startHour) * 60) + start.minute) * sizePerMinute() + linePadding, @@ -46,13 +53,12 @@ class Block extends StatelessWidget { (((end.hour - start.hour) * 60) + end.minute - start.minute) * sizePerMinute(), width: blockWidth, - color: Colors.red.withOpacity(0.5), + color: blockColor, ), ); } double sizePerMinute() { - // TODO(anyone): calculate this based on the size of the screen - return 80 / 60; + return hourHeight / 60; } } diff --git a/lib/src/models/table_theme.dart b/lib/src/models/table_theme.dart new file mode 100644 index 0000000..a4d399d --- /dev/null +++ b/lib/src/models/table_theme.dart @@ -0,0 +1,18 @@ +part of timetable; + +class TableTheme { + const TableTheme({ + this.lineColor = const Color(0x809E9E9E), + this.lineHeight = 2, + this.timeStyle = const TextStyle(), + }); + + /// The color of the lines. + final Color lineColor; + + /// The height of the lines. + final double lineHeight; + + /// The style of the time text. + final TextStyle timeStyle; +} diff --git a/lib/src/time_block.dart b/lib/src/models/time_block.dart similarity index 100% rename from lib/src/time_block.dart rename to lib/src/models/time_block.dart diff --git a/lib/src/table.dart b/lib/src/table.dart index 76ba919..0881e81 100644 --- a/lib/src/table.dart +++ b/lib/src/table.dart @@ -4,11 +4,15 @@ class Table extends StatelessWidget { const Table({ required this.startHour, required this.endHour, + this.columnHeight = 80, + this.theme = const TableTheme(), Key? key, }) : super(key: key); final int startHour; final int endHour; + final double columnHeight; + final TableTheme theme; @override Widget build(BuildContext context) { @@ -16,21 +20,22 @@ class Table extends StatelessWidget { children: [ for (int i = startHour; i <= endHour; i++) ...[ SizedBox( - height: i == endHour ? 40 : 80, + height: i == endHour ? columnHeight / 2 : columnHeight, child: Column( children: [ Row( children: [ Text( '${i.toString().padLeft(2, '0')}:00', + style: theme.timeStyle, ), const SizedBox( width: 5, ), Expanded( child: Container( - height: 2, - color: Colors.grey.withOpacity(0.5), + height: theme.lineHeight, + color: theme.lineColor, ), ) ], @@ -41,17 +46,16 @@ class Table extends StatelessWidget { margin: const EdgeInsets.only( left: 40, ), - height: 2, + height: theme.lineHeight, child: Row( children: [ for (int i = 0; i < 25; i++) ...[ Container( width: (MediaQuery.of(context).size.width - 40) / 25, - height: 2, - color: i.isEven - ? Colors.grey.withOpacity(0.5) - : Colors.transparent, + height: theme.lineHeight, + color: + i.isEven ? theme.lineColor : Colors.transparent, ), ], ], diff --git a/lib/src/timetable.dart b/lib/src/timetable.dart index 1cf722d..ac9a11f 100644 --- a/lib/src/timetable.dart +++ b/lib/src/timetable.dart @@ -7,6 +7,11 @@ class Timetable extends StatefulWidget { this.startHour = 0, this.endHour = 24, this.blockWidth = 50, + this.blockColor = const Color(0x80FF0000), + this.hourHeight = 80, + this.tablePaddingStart = 10, + this.tablePaddingEnd = 15, + this.theme = const TableTheme(), Key? key, }) : super(key: key); @@ -22,6 +27,21 @@ class Timetable extends StatefulWidget { /// The width of the block if there is no child final double blockWidth; + /// The color of the block if there is no child + final Color blockColor; + + /// The heigh of one hour in the timetable. + final double hourHeight; + + /// The padding between the table markings and the first block. + final double tablePaddingStart; + + /// The padding between the last block and the end of the table. + final double tablePaddingEnd; + + /// The theme of the timetable. + final TableTheme theme; + /// The scroll controller to control the scrolling of the timetable. final ScrollController? scrollController; @@ -57,9 +77,14 @@ class _TimetableState extends State { Table( startHour: widget.startHour, endHour: widget.endHour, + theme: widget.theme, ), Container( - margin: const EdgeInsets.only(left: 45), + margin: EdgeInsets.only( + left: _calculateTableTextSize().width + + widget.tablePaddingStart + + 5, + ), child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: IntrinsicHeight( @@ -71,14 +96,15 @@ class _TimetableState extends State { start: block.start, end: block.end, startHour: widget.startHour, + hourHeight: widget.hourHeight, blockWidth: widget.blockWidth, child: block.child, - ) + ), ], - // TODO(anyone): 80 needs to be a calculated value SizedBox( - width: 15, - height: 80 * (widget.endHour - widget.startHour) + 40, + width: widget.tablePaddingEnd, + height: widget.hourHeight * + (widget.endHour - widget.startHour + 0.5), ), ], ), @@ -98,12 +124,24 @@ class _TimetableState extends State { ? a : b, ); - var initialOffset = (80 * (widget.endHour - widget.startHour)) * - ((earliestStart.hour - widget.startHour) / - (widget.endHour - widget.startHour)); + var initialOffset = + (widget.hourHeight * (widget.endHour - widget.startHour)) * + ((earliestStart.hour - widget.startHour) / + (widget.endHour - widget.startHour)); _scrollController.jumpTo( initialOffset, ); }); } + + /// Calculates the width of 22:22 + Size _calculateTableTextSize() { + return (TextPainter( + text: TextSpan(text: '22:22', style: widget.theme.timeStyle), + maxLines: 1, + textScaleFactor: MediaQuery.of(context).textScaleFactor, + textDirection: TextDirection.ltr, + )..layout()) + .size; + } } diff --git a/lib/timetable.dart b/lib/timetable.dart index f517ef3..60a17d3 100644 --- a/lib/timetable.dart +++ b/lib/timetable.dart @@ -5,5 +5,6 @@ import 'package:flutter/scheduler.dart'; part 'src/timetable.dart'; part 'src/table.dart'; -part 'src/time_block.dart'; +part 'src/models/time_block.dart'; +part 'src/models/table_theme.dart'; part 'src/block.dart';