diff --git a/lib/src/components/common_components.dart b/lib/src/components/common_components.dart index 4d39a13d..d0a1d828 100644 --- a/lib/src/components/common_components.dart +++ b/lib/src/components/common_components.dart @@ -5,9 +5,13 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import '../calendar_event_data.dart'; import '../constants.dart'; +import '../extensions.dart'; import '../style/header_style.dart'; import '../typedefs.dart'; +import '../enumerations.dart'; +import 'components.dart'; class CalendarPageHeader extends StatelessWidget { /// When user taps on right arrow. @@ -117,3 +121,105 @@ class CalendarPageHeader extends StatelessWidget { ); } } + +/// This will be used in day and week view +class DefaultPressDetector extends StatelessWidget { + /// default press detector builder used in week and day view + const DefaultPressDetector({ + required this.date, + required this.height, + required this.width, + required this.heightPerMinute, + required this.minuteSlotSize, + this.onDateTap, + this.onDateLongPress, + }); + + final DateTime date; + final double height; + final double width; + final double heightPerMinute; + final MinuteSlotSize minuteSlotSize; + final DateTapCallback? onDateTap; + final DatePressCallback? onDateLongPress; + + @override + Widget build(BuildContext context) { + final heightPerSlot = minuteSlotSize.minutes * heightPerMinute; + final slots = (Constants.hoursADay * 60) ~/ minuteSlotSize.minutes; + + return SizedBox( + height: height, + width: width, + child: Stack( + children: [ + for (int i = 0; i < slots; i++) + Positioned( + top: heightPerSlot * i, + left: 0, + right: 0, + bottom: height - (heightPerSlot * (i + 1)), + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onLongPress: () => onDateLongPress?.call( + getSlotDateTime(i), + ), + onTap: () => onDateTap?.call( + getSlotDateTime(i), + ), + child: SizedBox( + width: width, + height: heightPerSlot, + ), + ), + ), + ], + ), + ); + } + + DateTime getSlotDateTime(int slot) => DateTime( + date.year, + date.month, + date.day, + 0, + (minuteSlotSize.minutes * slot), + ); +} + +/// This will be used in day and week view +class DefaultEventTile extends StatelessWidget { + const DefaultEventTile({ + required this.date, + required this.events, + required this.boundary, + required this.startDuration, + required this.endDuration, + }); + + final DateTime date; + final List> events; + final Rect boundary; + final DateTime startDuration; + final DateTime endDuration; + + @override + Widget build(BuildContext context) { + if (events.isNotEmpty) { + final event = events[0]; + return RoundedEventTile( + borderRadius: BorderRadius.circular(10.0), + title: event.title, + totalEvents: events.length - 1, + description: event.description, + padding: EdgeInsets.all(10.0), + backgroundColor: event.color, + margin: EdgeInsets.all(2.0), + titleStyle: event.titleStyle, + descriptionStyle: event.descriptionStyle, + ); + } else { + return SizedBox.shrink(); + } + } +} diff --git a/lib/src/day_view/day_view.dart b/lib/src/day_view/day_view.dart index 295e61d1..4e303983 100644 --- a/lib/src/day_view/day_view.dart +++ b/lib/src/day_view/day_view.dart @@ -9,6 +9,7 @@ import 'package:flutter/material.dart'; import '../calendar_constants.dart'; import '../calendar_controller_provider.dart'; import '../calendar_event_data.dart'; +import '../components/common_components.dart'; import '../components/day_view_components.dart'; import '../components/event_scroll_notifier.dart'; import '../components/safe_area_wrapper.dart'; @@ -611,48 +612,15 @@ class DayViewState extends State> { required double width, required double heightPerMinute, required MinuteSlotSize minuteSlotSize, - }) { - final heightPerSlot = minuteSlotSize.minutes * heightPerMinute; - final slots = (Constants.hoursADay * 60) ~/ minuteSlotSize.minutes; - - return Container( + }) => DefaultPressDetector( + date: date, height: height, width: width, - child: Stack( - children: [ - for (int i = 0; i < slots; i++) - Positioned( - top: heightPerSlot * i, - left: 0, - right: 0, - bottom: height - (heightPerSlot * (i + 1)), - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onLongPress: () => widget.onDateLongPress?.call( - DateTime( - date.year, - date.month, - date.day, - 0, - minuteSlotSize.minutes * i, - ), - ), - onTap: () => widget.onDateTap?.call( - DateTime( - date.year, - date.month, - date.day, - 0, - minuteSlotSize.minutes * i, - ), - ), - child: SizedBox(width: width, height: heightPerSlot), - ), - ), - ], - ), + heightPerMinute: heightPerMinute, + minuteSlotSize: minuteSlotSize, + onDateTap: widget.onDateTap, + onDateLongPress: widget.onDateLongPress, ); - } /// Default timeline builder this builder will be used if /// [widget.eventTileBuilder] is null @@ -669,23 +637,13 @@ class DayViewState extends State> { Rect boundary, DateTime startDuration, DateTime endDuration, - ) { - if (events.isNotEmpty) { - return RoundedEventTile( - borderRadius: BorderRadius.circular(10.0), - title: events[0].title, - totalEvents: events.length - 1, - description: events[0].description, - padding: EdgeInsets.all(10.0), - backgroundColor: events[0].color, - margin: EdgeInsets.all(2.0), - titleStyle: events[0].titleStyle, - descriptionStyle: events[0].descriptionStyle, - ); - } else { - return SizedBox.shrink(); - } - } + ) => DefaultEventTile( + date: date, + events: events, + boundary: boundary, + startDuration: startDuration, + endDuration: endDuration, + ); /// Default view header builder. This builder will be used if /// [widget.dayTitleBuilder] is null. diff --git a/lib/src/week_view/week_view.dart b/lib/src/week_view/week_view.dart index f5ae8c43..e922a78e 100644 --- a/lib/src/week_view/week_view.dart +++ b/lib/src/week_view/week_view.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; import '../calendar_constants.dart'; import '../calendar_controller_provider.dart'; import '../calendar_event_data.dart'; +import '../components/common_components.dart'; import '../components/components.dart'; import '../components/event_scroll_notifier.dart'; import '../components/safe_area_wrapper.dart'; @@ -676,49 +677,16 @@ class WeekViewState extends State> { required double width, required double heightPerMinute, required MinuteSlotSize minuteSlotSize, - }) { - final heightPerSlot = minuteSlotSize.minutes * heightPerMinute; - final slots = - ((Constants.hoursADay - _startHour) * 60) ~/ minuteSlotSize.minutes; - - return Container( - height: height, - width: width, - child: Stack( - children: [ - for (int i = 0; i < slots; i++) - Positioned( - top: heightPerSlot * i, - left: 0, - right: 0, - bottom: height - (heightPerSlot * (i + 1)), - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onLongPress: () => widget.onDateLongPress?.call( - DateTime( - date.year, - date.month, - date.day, - 0, - minuteSlotSize.minutes * i, - ), - ), - onTap: () => widget.onDateTap?.call( - DateTime( - date.year, - date.month, - date.day, - 0, - minuteSlotSize.minutes * i, - ), - ), - child: SizedBox(width: width, height: heightPerSlot), - ), - ), - ], - ), - ); - } + }) => + DefaultPressDetector( + date: date, + height: height, + width: width, + heightPerMinute: heightPerMinute, + minuteSlotSize: minuteSlotSize, + onDateTap: widget.onDateTap, + onDateLongPress: widget.onDateLongPress, + ); /// Default builder for week line. Widget _defaultWeekDayBuilder(DateTime date) { @@ -752,55 +720,27 @@ class WeekViewState extends State> { /// Default timeline builder this builder will be used if /// [widget.eventTileBuilder] is null /// - Widget _defaultTimeLineBuilder(DateTime date) { - final hour = ((date.hour - 1) % 12) + 1; - final timeLineString = (widget.timeLineStringBuilder != null) - ? widget.timeLineStringBuilder!(date) - : date.minute != 0 - ? "$hour:${date.minute}" - : "$hour ${date.hour ~/ 12 == 0 ? "am" : "pm"}"; - - return Transform.translate( - offset: Offset(0, -7.5), - child: Padding( - padding: const EdgeInsets.only(right: 7.0), - child: Text( - timeLineString, - textAlign: TextAlign.right, - style: TextStyle( - fontSize: 15.0, - ), - ), - ), - ); - } + Widget _defaultTimeLineBuilder(DateTime date) => DefaultTimeLineMark( + date: date, + timeStringBuilder: widget.timeLineStringBuilder, + ); /// Default timeline builder. This builder will be used if /// [widget.eventTileBuilder] is null Widget _defaultEventTileBuilder( - DateTime date, - List> events, - Rect boundary, - DateTime startDuration, - DateTime endDuration) { - if (events.isNotEmpty) { - return RoundedEventTile( - borderRadius: BorderRadius.circular(6.0), - title: events[0].title, - titleStyle: events[0].titleStyle ?? - TextStyle( - fontSize: 12, - color: events[0].color.accent, - ), - descriptionStyle: events[0].descriptionStyle, - totalEvents: events.length, - padding: EdgeInsets.all(7.0), - backgroundColor: events[0].color, + DateTime date, + List> events, + Rect boundary, + DateTime startDuration, + DateTime endDuration, + ) => + DefaultEventTile( + date: date, + events: events, + boundary: boundary, + startDuration: startDuration, + endDuration: endDuration, ); - } else { - return Container(); - } - } /// Default view header builder. This builder will be used if /// [widget.dayTitleBuilder] is null.