diff --git a/example/lib/main.dart b/example/lib/main.dart index 3e6043d..861c34b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -95,6 +95,12 @@ class _TimetableExampleState extends State { ], ), body: Timetable( + theme: TimetableThemeData( + hourTextStyle: TextStyle(fontSize: 9, color: Colors.blueGrey), + formatHour: (time) => + '${time.hourOf12HourClock} ${time.hourOfDay > 11 ? "PM" : "AM"}', + hourColumnWidth: 40, + ), controller: _controller, onEventBackgroundTap: (start, isAllDay) { _showSnackBar('Background tapped $start is all day event $isAllDay'); diff --git a/example/pubspec.lock b/example/pubspec.lock index 5ce441d..709e742 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,14 +7,14 @@ packages: name: black_hole_flutter url: "https://pub.dartlang.org" source: hosted - version: "0.2.12" + version: "0.2.15" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0-nullsafety.3" charcode: dependency: transitive description: @@ -28,7 +28,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" + version: "1.15.0-nullsafety.3" convert: dependency: transitive description: @@ -49,7 +49,7 @@ packages: name: dartx url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.5.0" flutter: dependency: "direct main" description: flutter @@ -61,7 +61,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.3" path: dependency: transitive description: @@ -122,14 +122,14 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0-nullsafety.3" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.3" sdks: - dart: ">=2.7.0 <3.0.0" + dart: ">=2.10.0-110 <2.11.0" flutter: ">=1.17.0" diff --git a/lib/src/content/date_hours_painter.dart b/lib/src/content/date_hours_painter.dart index 2e026e9..4ef39aa 100644 --- a/lib/src/content/date_hours_painter.dart +++ b/lib/src/content/date_hours_painter.dart @@ -8,13 +8,16 @@ class DateHoursPainter extends CustomPainter { DateHoursPainter({ @required this.textStyle, @required this.textDirection, + String Function(LocalTime) formatHour, }) : assert(textStyle != null), assert(textDirection != null), _painters = [ for (final h in innerDateHours) TextPainter( text: TextSpan( - text: _pattern.format(LocalTime(h, 0, 0)), + text: formatHour != null + ? formatHour(LocalTime(h, 0, 0)) + : _pattern.format(LocalTime(h, 0, 0)), style: textStyle, ), textDirection: textDirection, diff --git a/lib/src/content/timetable_content.dart b/lib/src/content/timetable_content.dart index 769a6fd..b8efd15 100644 --- a/lib/src/content/timetable_content.dart +++ b/lib/src/content/timetable_content.dart @@ -38,7 +38,7 @@ class TimetableContent extends StatelessWidget { child: Row( children: [ Container( - width: hourColumnWidth, + width: timetableTheme.hourColumnWidth ?? hourColumnWidth, padding: EdgeInsets.only(right: 12), child: CustomPaint( painter: DateHoursPainter( @@ -47,6 +47,7 @@ class TimetableContent extends StatelessWidget { color: context.theme.disabledOnBackground, ), textDirection: context.directionality, + formatHour: timetableTheme.formatHour, ), size: Size.infinite, ), diff --git a/lib/src/header/timetable_header.dart b/lib/src/header/timetable_header.dart index c0d50ec..aae50c3 100644 --- a/lib/src/header/timetable_header.dart +++ b/lib/src/header/timetable_header.dart @@ -36,7 +36,7 @@ class TimetableHeader extends StatelessWidget { return Row( children: [ SizedBox( - width: hourColumnWidth, + width: context?.timetableTheme?.hourColumnWidth ?? hourColumnWidth, child: ValueListenableBuilder( valueListenable: controller.dateListenable, builder: (context, date, _) { diff --git a/lib/src/theme.dart b/lib/src/theme.dart index d0bd2cf..24d4d9d 100644 --- a/lib/src/theme.dart +++ b/lib/src/theme.dart @@ -20,6 +20,8 @@ class TimetableThemeData { this.dateIndicatorTextStyle, this.allDayEventHeight, this.hourTextStyle, + this.hourColumnWidth, + this.formatHour, this.timeIndicatorColor, this.dividerColor, this.minimumHourHeight, @@ -106,6 +108,14 @@ class TimetableThemeData { /// [TextStyle] used to display the hours of the day. final TextStyle hourTextStyle; + /// Width of hour of day column + /// + /// Default to 48 + final double hourColumnWidth; + + /// [HourFormatter] used to format the hours of the day string. + final HourFormatter formatHour; + /// [Color] for painting the current time indicator. final Color timeIndicatorColor; @@ -177,6 +187,8 @@ class TimetableThemeData { dateIndicatorTextStyle, allDayEventHeight, hourTextStyle, + hourColumnWidth, + formatHour, timeIndicatorColor, dividerColor, minimumHourHeight, @@ -273,3 +285,5 @@ extension TimetableThemeBuildContext on BuildContext { /// Shortcut for `TimetableTheme.of(context)`. TimetableThemeData get timetableTheme => TimetableTheme.of(this); } + +typedef HourFormatter = String Function(LocalTime time); diff --git a/pubspec.yaml b/pubspec.yaml index 49d5075..8ff2a1b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,11 +13,11 @@ dependencies: black_hole_flutter: ^0.2.11 collection: ^1.14.11 - dartx: ^0.4.0 + dartx: ^0.5.0 meta: ^1.1.8 pedantic: ^1.8.0+1 rxdart: ^0.24.0 - time_machine: ^0.9.12 + time_machine: 0.9.12 dev_dependencies: flutter_test: diff --git a/test/content/date_hours_painter_test.dart b/test/content/date_hours_painter_test.dart new file mode 100644 index 0000000..cb58af3 --- /dev/null +++ b/test/content/date_hours_painter_test.dart @@ -0,0 +1,21 @@ +import 'package:flutter/painting.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:timetable/src/content/date_hours_painter.dart'; + +void main() { + testWidgets('Format hour', (tester) async { + final painter = DateHoursPainter( + textDirection: TextDirection.ltr, textStyle: TextStyle()); + await tester.pumpWidget(CustomPaint(painter: painter)); + // find.text('01:00') does not work with text painters :( + }); + testWidgets('Custom hour format', (tester) async { + final painter = DateHoursPainter( + textDirection: TextDirection.ltr, + textStyle: TextStyle(), + formatHour: (x) => '${x.hourOfDay}', + ); + await tester.pumpWidget(CustomPaint(painter: painter)); + }); +} diff --git a/test/theme_test.dart b/test/theme_test.dart new file mode 100644 index 0000000..2486245 --- /dev/null +++ b/test/theme_test.dart @@ -0,0 +1,15 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:time_machine/time_machine.dart'; +import 'package:timetable/timetable.dart'; + +void main() { + test('formatHour is null by default', () { + final theme = TimetableThemeData(); + expect(theme.formatHour, isNull); + }); + test('format hour', () { + final theme = TimetableThemeData(formatHour: (time) => '${time.hourOfDay}'); + final hourString = theme.formatHour(LocalTime(9, 42, 00)); + expect(hourString, '9'); + }); +}