You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PatientApp-KKUMC/lib/widgets/input/date_picker/date_picker.dart

1460 lines
48 KiB
Dart

// import 'dart:async';
// import 'dart:math' as math;
//
// import 'package:flutter/gestures.dart' show DragStartBehavior;
// import 'package:flutter/material.dart';
// import 'package:flutter/rendering.dart';
// import 'package:flutter/services.dart';
// import 'package:flutter/widgets.dart';
//
// import 'button_actions.dart';
// import 'era_mode.dart';
//
// /// Initial display mode of the date picker dialog.
// ///
// /// Date picker UI mode for either showing a list of available years or a
// /// monthly calendar initially in the dialog shown by calling [showDatePicker].
// ///
//
// const Duration _kMonthScrollDuration = Duration(milliseconds: 200);
// const double _kDayPickerRowHeight = 42.0;
// const int _kMaxDayPickerRowCount = 6; // A 31 day month that starts on Saturday.
// // Two extra rows: one for the day-of-week header and one for the month header.
// const double _kMaxDayPickerHeight =
// _kDayPickerRowHeight * (_kMaxDayPickerRowCount + 2);
//
// /// Shows the selected date in large font and toggles between year and day mode
// class _DatePickerHeader extends StatelessWidget {
// const _DatePickerHeader({
// Key key,
// @required this.selectedDate,
// @required this.mode,
// @required this.onModeChanged,
// @required this.orientation,
// this.yearSelectAllowed,
// this.era,
// this.borderRadius,
// this.imageHeader,
// this.description = "",
// this.fontFamily,
// }) : assert(selectedDate != null),
// assert(mode != null),
// assert(orientation != null),
// super(key: key);
//
// final DateTime selectedDate;
// final DatePickerMode mode;
// final ValueChanged<DatePickerMode> onModeChanged;
// final Orientation orientation;
// final bool yearSelectAllowed;
//
// /// Era custom
// final EraMode era;
//
// /// Border
// final double borderRadius;
//
// /// Header
// final ImageProvider imageHeader;
//
// /// Header description
// final String description;
//
// /// Font
// final String fontFamily;
//
// void _handleChangeMode(DatePickerMode value) {
// if (value != mode) onModeChanged(value);
// }
//
// @override
// Widget build(BuildContext context) {
// final MaterialLocalizations localizations =
// MaterialLocalizations.of(context);
// final ThemeData themeData = Theme.of(context);
// final TextTheme headerTextTheme = themeData.primaryTextTheme;
// Color dayColor;
// Color yearColor;
// switch (themeData.primaryColorBrightness) {
// case Brightness.light:
// dayColor = mode == DatePickerMode.day ? Colors.black87 : Colors.black54;
// yearColor =
// mode == DatePickerMode.year ? Colors.black87 : Colors.black54;
// break;
// case Brightness.dark:
// dayColor = mode == DatePickerMode.day ? Colors.white : Colors.white70;
// yearColor = mode == DatePickerMode.year ? Colors.white : Colors.white70;
// break;
// }
// final TextStyle dayStyle = headerTextTheme.headline4.copyWith(
// color: dayColor, fontFamily: fontFamily, fontWeight: FontWeight.w800);
// final TextStyle yearStyle = headerTextTheme.subtitle1.copyWith(
// color: yearColor, fontFamily: fontFamily, fontWeight: FontWeight.w800);
//
// Color backgroundColor;
// backgroundColor = themeData.primaryColor;
//
// EdgeInsets padding;
// MainAxisAlignment mainAxisAlignment;
// switch (orientation) {
// case Orientation.portrait:
// padding = const EdgeInsets.all(16.0);
// mainAxisAlignment = MainAxisAlignment.center;
// break;
// case Orientation.landscape:
// padding = const EdgeInsets.all(8.0);
// mainAxisAlignment = MainAxisAlignment.start;
// break;
// }
//
// final Widget yearButton = IgnorePointer(
// ignoring: mode != DatePickerMode.day,
// ignoringSemantics: false,
// child: IgnorePointer(
// ignoring: !yearSelectAllowed ?? true,
// child: _DateHeaderButton(
// color: Colors.transparent,
// onTap: Feedback.wrapForTap(
// () => _handleChangeMode(DatePickerMode.year),
// context,
// ),
// child: Semantics(
// selected: mode == DatePickerMode.year,
// child: Text(
// "${calculateYearEra(era, selectedDate.year)}",
// style: yearStyle,
// ),
// ),
// ),
// ),
// );
//
// final Widget dayButton = IgnorePointer(
// ignoring: mode == DatePickerMode.day,
// ignoringSemantics: false,
// child: _DateHeaderButton(
// color: Colors.transparent,
// onTap: Feedback.wrapForTap(
// () => _handleChangeMode(DatePickerMode.day),
// context,
// ),
// child: Semantics(
// selected: mode == DatePickerMode.day,
// child: Text(
// localizations.formatMediumDate(selectedDate),
// style: dayStyle,
// ),
// ),
// ),
// );
//
// BorderRadius borderRadiusData = BorderRadius.only(
// topLeft: Radius.circular(borderRadius),
// topRight: Radius.circular(borderRadius),
// );
//
// if (orientation == Orientation.landscape) {
// borderRadiusData = BorderRadius.only(
// topLeft: Radius.circular(borderRadius),
// bottomLeft: Radius.circular(borderRadius),
// );
// }
//
// return Container(
// decoration: BoxDecoration(
// image: imageHeader != null
// ? DecorationImage(image: imageHeader, fit: BoxFit.cover)
// : null,
// color: backgroundColor,
// borderRadius: borderRadiusData,
// ),
// padding: padding,
// child: Column(
// mainAxisAlignment: mainAxisAlignment,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: <Widget>[
// yearButton,
// dayButton,
// const SizedBox(height: 4.0),
// Visibility(
// visible: description.isNotEmpty,
// child: Padding(
// padding: EdgeInsets.symmetric(horizontal: 12),
// child: Text(
// description,
// style: TextStyle(
// color: yearColor,
// fontSize: 12,
// fontFamily: fontFamily,
// ),
// ),
// ),
// )
// ],
// ),
// );
// }
// }
//
// class _DateHeaderButton extends StatelessWidget {
// const _DateHeaderButton({
// Key key,
// this.onTap,
// this.color,
// this.child,
// }) : super(key: key);
//
// final VoidCallback onTap;
// final Color color;
// final Widget child;
//
// @override
// Widget build(BuildContext context) {
// final ThemeData theme = Theme.of(context);
//
// return Material(
// type: MaterialType.button,
// color: color,
// child: InkWell(
// borderRadius: kMaterialEdges[MaterialType.button],
// highlightColor: theme.highlightColor,
// splashColor: theme.splashColor,
// onTap: onTap,
// child: Container(
// padding: const EdgeInsets.symmetric(horizontal: 8.0),
// child: child,
// ),
// ),
// );
// }
// }
//
// class _DayPickerGridDelegate extends SliverGridDelegate {
// const _DayPickerGridDelegate();
//
// @override
// SliverGridLayout getLayout(SliverConstraints constraints) {
// const int columnCount = DateTime.daysPerWeek;
// final double tileWidth = constraints.crossAxisExtent / columnCount;
// final double viewTileHeight =
// constraints.viewportMainAxisExtent / (_kMaxDayPickerRowCount + 1);
// final double tileHeight = math.max(_kDayPickerRowHeight, viewTileHeight);
//
// return SliverGridRegularTileLayout(
// crossAxisCount: columnCount,
// mainAxisStride: tileHeight,
// crossAxisStride: tileWidth,
// childMainAxisExtent: tileHeight,
// childCrossAxisExtent: tileWidth,
// reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection),
// );
// }
//
// @override
// bool shouldRelayout(_DayPickerGridDelegate oldDelegate) => false;
// }
//
// const _DayPickerGridDelegate _kDayPickerGridDelegate = _DayPickerGridDelegate();
//
// /// Displays the days of a given month and allows choosing a day.
// ///
// /// The days are arranged in a rectangular grid with one column for each day of
// /// the week.
// ///
// /// The day picker widget is rarely used directly. Instead, consider using
// /// [showDatePicker], which creates a date picker dialog.
// ///
// /// See also:
// ///
// /// * [showDatePicker], which shows a dialog that contains a material design
// /// date picker.
// /// * [showTimePicker], which shows a dialog that contains a material design
// /// time picker.
// class DayPicker extends StatelessWidget {
// /// Creates a day picker.
// ///
// /// Rarely used directly. Instead, typically used as part of a [MonthPicker].
// DayPicker({
// Key key,
// @required this.selectedDate,
// @required this.currentDate,
// @required this.onChanged,
// @required this.firstDate,
// @required this.lastDate,
// @required this.displayedMonth,
// this.selectableDayPredicate,
// this.dragStartBehavior = DragStartBehavior.start,
// this.era,
// this.locale,
// this.fontFamily,
// }) : assert(selectedDate != null),
// assert(currentDate != null),
// assert(onChanged != null),
// assert(displayedMonth != null),
// assert(dragStartBehavior != null),
// assert(!firstDate.isAfter(lastDate)),
// assert(selectedDate.isAfter(firstDate) ||
// selectedDate.isAtSameMomentAs(firstDate)),
// super(key: key);
//
// /// The currently selected date.
// ///
// /// This date is highlighted in the picker.
// final DateTime selectedDate;
//
// /// The current date at the time the picker is displayed.
// final DateTime currentDate;
//
// /// Called when the user picks a day.
// final ValueChanged<DateTime> onChanged;
//
// /// The earliest date the user is permitted to pick.
// final DateTime firstDate;
//
// /// The latest date the user is permitted to pick.
// final DateTime lastDate;
//
// /// The month whose days are displayed by this picker.
// final DateTime displayedMonth;
//
// /// Optional user supplied predicate function to customize selectable days.
// final SelectableDayPredicate selectableDayPredicate;
//
// final EraMode era;
// final Locale locale;
//
// final String fontFamily;
//
// /// Determines the way that drag start behavior is handled.
// ///
// /// If set to [DragStartBehavior.start], the drag gesture used to scroll a
// /// date picker wheel will begin upon the detection of a drag gesture. If set
// /// to [DragStartBehavior.down] it will begin when a down event is first
// /// detected.
// ///
// /// In general, setting this to [DragStartBehavior.start] will make drag
// /// animation smoother and setting it to [DragStartBehavior.down] will make
// /// drag behavior feel slightly more reactive.
// ///
// /// By default, the drag start behavior is [DragStartBehavior.start].
// ///
// /// See also:
// ///
// /// * [DragGestureRecognizer.dragStartBehavior], which gives an example for the different behaviors.
// final DragStartBehavior dragStartBehavior;
//
// /// Builds widgets showing abbreviated days of week. The first widget in the
// /// returned list corresponds to the first day of week for the current locale.
// ///
// /// Examples:
// ///
// /// ```
// /// ┌ Sunday is the first day of week in the US (en_US)
// /// |
// /// S M T W T F S <-- the returned list contains these widgets
// /// _ _ _ _ _ 1 2
// /// 3 4 5 6 7 8 9
// ///
// /// ┌ But it's Monday in the UK (en_GB)
// /// |
// /// M T W T F S S <-- the returned list contains these widgets
// /// _ _ _ _ 1 2 3
// /// 4 5 6 7 8 9 10
// /// ```
// List<Widget> _getDayHeaders(
// TextStyle headerStyle,
// MaterialLocalizations localizations,
// ) {
// final List<Widget> result = <Widget>[];
// for (int i = localizations.firstDayOfWeekIndex; true; i = (i + 1) % 7) {
// final String weekday = localizations.narrowWeekdays[i];
// result.add(ExcludeSemantics(
// child: Center(
// child: Text(weekday,
// style: TextStyle(
// fontWeight: FontWeight.w800,
// fontFamily: "HKGrotesk",
// color: Color.fromRGBO(78, 62, 253, 1.0)))),
// ));
// if (i == (localizations.firstDayOfWeekIndex - 1) % 7) break;
// }
//
// return result;
// }
//
// // Do not use this directly - call getDaysInMonth instead.
// static const List<int> _daysInMonth = <int>[
// 31,
// -1,
// 31,
// 30,
// 31,
// 30,
// 31,
// 31,
// 30,
// 31,
// 30,
// 31,
// ];
//
// /// Returns the number of days in a month, according to the proleptic
// /// Gregorian calendar.
// ///
// /// This applies the leap year logic introduced by the Gregorian reforms of
// /// 1582. It will not give valid results for dates prior to that time.
// static int getDaysInMonth(int year, int month) {
// if (month == DateTime.february) {
// final bool isLeapYear =
// (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
// if (isLeapYear) return 29;
// return 28;
// }
// return _daysInMonth[month - 1];
// }
//
// /// Computes the offset from the first day of week that the first day of the
// /// [month] falls on.
// ///
// /// For example, September 1, 2017 falls on a Friday, which in the calendar
// /// localized for United States English appears as:
// ///
// /// ```
// /// S M T W T F S
// /// _ _ _ _ _ 1 2
// /// ```
// ///
// /// The offset for the first day of the months is the number of leading blanks
// /// in the calendar, i.e. 5.
// ///
// /// The same date localized for the Russian calendar has a different offset,
// /// because the first day of week is Monday rather than Sunday:
// ///
// /// ```
// /// M T W T F S S
// /// _ _ _ _ 1 2 3
// /// ```
// ///
// /// So the offset is 4, rather than 5.
// ///
// /// This code consolidates the following:
// ///
// /// - [DateTime.weekday] provides a 1-based index into days of week, with 1
// /// falling on Monday.
// /// - [MaterialLocalizations.firstDayOfWeekIndex] provides a 0-based index
// /// into the [MaterialLocalizations.narrowWeekdays] list.
// /// - [MaterialLocalizations.narrowWeekdays] list provides localized names of
// /// days of week, always starting with Sunday and ending with Saturday.
// int _computeFirstDayOffset(
// int year, int month, MaterialLocalizations localizations) {
// // 0-based day of week, with 0 representing Monday.
// final int weekdayFromMonday = DateTime(year, month).weekday - 1;
// // 0-based day of week, with 0 representing Sunday.
// final int firstDayOfWeekFromSunday = localizations.firstDayOfWeekIndex;
// // firstDayOfWeekFromSunday recomputed to be Monday-based
// final int firstDayOfWeekFromMonday = (firstDayOfWeekFromSunday - 1) % 7;
// // Number of days between the first day of week appearing on the calendar,
// // and the day corresponding to the 1-st of the month.
// return (weekdayFromMonday - firstDayOfWeekFromMonday) % 7;
// }
//
// @override
// Widget build(BuildContext context) {
// final ThemeData themeData = Theme.of(context);
// final MaterialLocalizations localizations =
// MaterialLocalizations.of(context);
// final int year = displayedMonth.year;
// final int month = displayedMonth.month;
// final int daysInMonth = getDaysInMonth(year, month);
// final int firstDayOffset = _computeFirstDayOffset(
// year,
// month,
// localizations,
// );
//
// final List<Widget> labels = _getDayHeaders(
// themeData.textTheme.caption.copyWith(color: themeData.primaryColor),
// localizations);
// for (int i = 0; true; i += 1) {
// // 1-based day of month, e.g. 1-31 for January, and 1-29 for February on
// // a leap year.
// final int day = i - firstDayOffset + 1;
// if (day > daysInMonth) break;
// if (day < 1) {
// labels.add(Container());
// } else {
// final DateTime dayToBuild = DateTime(year, month, day);
// final bool disabled = dayToBuild.isAfter(lastDate) ||
// dayToBuild.isBefore(firstDate) ||
// (selectableDayPredicate != null &&
// !selectableDayPredicate(dayToBuild));
//
// BoxDecoration decoration;
// TextStyle itemStyle = themeData.textTheme.bodyText2
// .copyWith(fontFamily: fontFamily, fontWeight: FontWeight.w800);
//
// final bool isSelectedDay = selectedDate.year == year &&
// selectedDate.month == month &&
// selectedDate.day == day;
// if (isSelectedDay) {
// // The selected day gets a circle background highlight, and a contrasting text color.
// itemStyle = themeData.accentTextTheme.bodyText1.copyWith(
// fontFamily: fontFamily,
// fontWeight: FontWeight.w800,
// color: Colors.white);
// decoration = BoxDecoration(
// color: themeData.primaryColor,
// shape: BoxShape.circle,
// );
// } else if (disabled) {
// itemStyle = themeData.textTheme.bodyText2.copyWith(
// color: themeData.disabledColor,
// fontFamily: fontFamily,
// fontWeight: FontWeight.w800,
// );
// } else if (currentDate.year == year &&
// currentDate.month == month &&
// currentDate.day == day) {
// // The current day gets a different text color.
// itemStyle = themeData.textTheme.bodyText1.copyWith(
// color: themeData.accentColor,
// fontFamily: fontFamily,
// fontWeight: FontWeight.w800);
// }
//
// Widget dayWidget = Container(
// decoration: decoration,
// child: Center(
// child: Semantics(
// // We want the day of month to be spoken first irrespective of the
// // locale-specific preferences or TextDirection. This is because
// // an accessibility user is more likely to be interested in the
// // day of month before the rest of the date, as they are looking
// // for the day of month. To do that we prepend day of month to the
// // formatted full date.
// label:
// '${localizations.formatDecimal(day)}, ${localizations.formatFullDate(dayToBuild)}',
// selected: isSelectedDay,
// sortKey: OrdinalSortKey(day.toDouble()),
// child: ExcludeSemantics(
// child: Text(localizations.formatDecimal(day), style: itemStyle),
// ),
// ),
// ),
// );
//
// if (!disabled) {
// dayWidget = GestureDetector(
// behavior: HitTestBehavior.opaque,
// onTap: () {
// onChanged(dayToBuild);
// },
// child: dayWidget,
// dragStartBehavior: dragStartBehavior,
// );
// }
//
// labels.add(dayWidget);
// }
// }
//
// String monthYearHeader = "";
// monthYearHeader = localizations.formatMonthYear(displayedMonth);
//
// return Padding(
// padding: const EdgeInsets.symmetric(horizontal: 8.0),
// child: Column(
// children: <Widget>[
// Container(
// height: _kDayPickerRowHeight,
// child: Center(
// child: ExcludeSemantics(
// child: Text(
// monthYearHeader,
// style: themeData.textTheme.subtitle1.copyWith(
// fontFamily: fontFamily, fontWeight: FontWeight.w800),
// ),
// ),
// ),
// ),
// Flexible(
// child: GridView.custom(
// gridDelegate: _kDayPickerGridDelegate,
// childrenDelegate: SliverChildListDelegate(
// labels,
// addRepaintBoundaries: false,
// ),
// padding: EdgeInsets.zero,
// ),
// ),
// ],
// ),
// );
// }
// }
//
// /// A scrollable list of months to allow picking a month.
// ///
// /// Shows the days of each month in a rectangular grid with one column for each
// /// day of the week.
// ///
// /// The month picker widget is rarely used directly. Instead, consider using
// /// [showDatePicker], which creates a date picker dialog.
// ///
// /// See also:
// ///
// /// * [showDatePicker], which shows a dialog that contains a material design
// /// date picker.
// /// * [showTimePicker], which shows a dialog that contains a material design
// /// time picker.
// class MonthPicker extends StatefulWidget {
// /// Creates a month picker.
// ///
// /// Rarely used directly. Instead, typically used as part of the dialog shown
// /// by [showDatePicker].
// MonthPicker({
// Key key,
// @required this.selectedDate,
// @required this.onChanged,
// @required this.firstDate,
// @required this.lastDate,
// this.selectableDayPredicate,
// this.dragStartBehavior = DragStartBehavior.start,
// this.era,
// this.locale,
// this.fontFamily,
// }) : assert(selectedDate != null),
// assert(onChanged != null),
// assert(!firstDate.isAfter(lastDate)),
// assert(selectedDate.isAfter(firstDate) ||
// selectedDate.isAtSameMomentAs(firstDate)),
// super(key: key);
//
// /// The currently selected date.
// ///
// /// This date is highlighted in the picker.
// final DateTime selectedDate;
//
// /// Called when the user picks a month.
// final ValueChanged<DateTime> onChanged;
//
// /// The earliest date the user is permitted to pick.
// final DateTime firstDate;
//
// /// The latest date the user is permitted to pick.
// final DateTime lastDate;
//
// /// Optional user supplied predicate function to customize selectable days.
// final SelectableDayPredicate selectableDayPredicate;
//
// /// {@macro flutter.widgets.scrollable.dragStartBehavior}
// final DragStartBehavior dragStartBehavior;
//
// /// Optional era year.
// final EraMode era;
// final Locale locale;
//
// /// Font
// final String fontFamily;
//
// @override
// _MonthPickerState createState() => _MonthPickerState();
// }
//
// class _MonthPickerState extends State<MonthPicker>
// with SingleTickerProviderStateMixin {
// static final Animatable<double> _chevronOpacityTween =
// Tween<double>(begin: 1.0, end: 0.0)
// .chain(CurveTween(curve: Curves.easeInOut));
//
// @override
// void initState() {
// super.initState();
// // Initially display the pre-selected date.
// final int monthPage = _monthDelta(widget.firstDate, widget.selectedDate);
// _dayPickerController = PageController(initialPage: monthPage);
// _handleMonthPageChanged(monthPage);
// _updateCurrentDate();
//
// // Setup the fade animation for chevrons
// _chevronOpacityController = AnimationController(
// duration: const Duration(milliseconds: 250),
// vsync: this,
// );
// _chevronOpacityAnimation = _chevronOpacityController.drive(
// _chevronOpacityTween,
// );
// }
//
// @override
// void didUpdateWidget(MonthPicker oldWidget) {
// super.didUpdateWidget(oldWidget);
// if (widget.selectedDate != oldWidget.selectedDate) {
// final int monthPage = _monthDelta(widget.firstDate, widget.selectedDate);
// _dayPickerController = PageController(initialPage: monthPage);
// _handleMonthPageChanged(monthPage);
// }
// }
//
// MaterialLocalizations localizations;
// TextDirection textDirection;
//
// @override
// void didChangeDependencies() {
// super.didChangeDependencies();
// localizations = MaterialLocalizations.of(context);
// textDirection = Directionality.of(context);
// }
//
// DateTime _todayDate;
// DateTime _currentDisplayedMonthDate;
// Timer _timer;
// PageController _dayPickerController;
// AnimationController _chevronOpacityController;
// Animation<double> _chevronOpacityAnimation;
//
// void _updateCurrentDate() {
// _todayDate = DateTime.now();
// final DateTime tomorrow =
// DateTime(_todayDate.year, _todayDate.month, _todayDate.day + 1);
// Duration timeUntilTomorrow = tomorrow.difference(_todayDate);
// // so we don't miss it by rounding
// timeUntilTomorrow += const Duration(seconds: 1);
// _timer?.cancel();
// _timer = Timer(timeUntilTomorrow, () {
// setState(() => _updateCurrentDate());
// });
// }
//
// static int _monthDelta(DateTime startDate, DateTime endDate) {
// return (endDate.year - startDate.year) * 12 +
// endDate.month -
// startDate.month;
// }
//
// /// Add months to a month truncated date.
// DateTime _addMonthsToMonthDate(DateTime monthDate, int monthsToAdd) {
// return DateTime(
// monthDate.year + monthsToAdd ~/ 12,
// monthDate.month + monthsToAdd % 12,
// );
// }
//
// Widget _buildItems(BuildContext context, int index) {
// final DateTime month = _addMonthsToMonthDate(widget.firstDate, index);
// return DayPicker(
// key: ValueKey<DateTime>(month),
// selectedDate: widget.selectedDate,
// currentDate: _todayDate,
// onChanged: widget.onChanged,
// firstDate: widget.firstDate,
// lastDate: widget.lastDate,
// displayedMonth: month,
// selectableDayPredicate: widget.selectableDayPredicate,
// dragStartBehavior: widget.dragStartBehavior,
// era: widget.era,
// locale: widget.locale,
// fontFamily: widget.fontFamily,
// );
// }
//
// void _handleNextMonth() {
// if (!_isDisplayingLastMonth) {
// SemanticsService.announce(
// localizations.formatMonthYear(_nextMonthDate),
// textDirection,
// );
// _dayPickerController.nextPage(
// duration: _kMonthScrollDuration,
// curve: Curves.ease,
// );
// }
// }
//
// void _handlePreviousMonth() {
// if (!_isDisplayingFirstMonth) {
// SemanticsService.announce(
// localizations.formatMonthYear(_previousMonthDate),
// textDirection,
// );
// _dayPickerController.previousPage(
// duration: _kMonthScrollDuration,
// curve: Curves.ease,
// );
// }
// }
//
// /// True if the earliest allowable month is displayed.
// bool get _isDisplayingFirstMonth {
// return !_currentDisplayedMonthDate.isAfter(
// DateTime(widget.firstDate.year, widget.firstDate.month),
// );
// }
//
// /// True if the latest allowable month is displayed.
// bool get _isDisplayingLastMonth {
// return !_currentDisplayedMonthDate.isBefore(
// DateTime(widget.lastDate.year, widget.lastDate.month),
// );
// }
//
// DateTime _previousMonthDate;
// DateTime _nextMonthDate;
//
// void _handleMonthPageChanged(int monthPage) {
// setState(() {
// _previousMonthDate = _addMonthsToMonthDate(
// widget.firstDate,
// monthPage - 1,
// );
// _currentDisplayedMonthDate = _addMonthsToMonthDate(
// widget.firstDate,
// monthPage,
// );
// _nextMonthDate = _addMonthsToMonthDate(widget.firstDate, monthPage + 1);
// });
// }
//
// @override
// Widget build(BuildContext context) {
// return SizedBox(
// // The month picker just adds month navigation to the day picker, so make
// // it the same height as the DayPicker
// height: _kMaxDayPickerHeight,
// child: Stack(
// children: <Widget>[
// Semantics(
// sortKey: _MonthPickerSortKey.calendar,
// child: NotificationListener<ScrollStartNotification>(
// onNotification: (_) {
// _chevronOpacityController.forward();
// return false;
// },
// child: NotificationListener<ScrollEndNotification>(
// onNotification: (_) {
// _chevronOpacityController.reverse();
// return false;
// },
// child: PageView.builder(
// physics: BouncingScrollPhysics(),
// dragStartBehavior: widget.dragStartBehavior,
// key: ValueKey<DateTime>(widget.selectedDate),
// controller: _dayPickerController,
// scrollDirection: Axis.horizontal,
// itemCount: _monthDelta(widget.firstDate, widget.lastDate) + 1,
// itemBuilder: _buildItems,
// onPageChanged: _handleMonthPageChanged,
// ),
// ),
// ),
// ),
//
// /// Arrow Left
// PositionedDirectional(
// top: 0.0,
// start: 8.0,
// child: Semantics(
// sortKey: _MonthPickerSortKey.previousMonth,
// child: FadeTransition(
// opacity: _chevronOpacityAnimation,
// child: IconButton(
// disabledColor:
// Theme.of(context).disabledColor.withOpacity(0.2),
// color: Theme.of(context).disabledColor,
// icon: const Icon(Icons.chevron_left_sharp),
// tooltip: _isDisplayingFirstMonth
// ? null
// : '${localizations.previousMonthTooltip} ${localizations.formatMonthYear(_previousMonthDate)}',
// onPressed: _isDisplayingFirstMonth == true
// ? null
// : _handlePreviousMonth,
// ),
// ),
// ),
// ),
//
// /// Arrow Right
// PositionedDirectional(
// top: 0.0,
// end: 8.0,
// child: Semantics(
// sortKey: _MonthPickerSortKey.nextMonth,
// child: FadeTransition(
// opacity: _chevronOpacityAnimation,
// child: IconButton(
// disabledColor:
// Theme.of(context).disabledColor.withOpacity(0.2),
// color: Theme.of(context).disabledColor,
// icon: const Icon(Icons.chevron_right_sharp),
// tooltip: _isDisplayingLastMonth
// ? null
// : '${localizations.nextMonthTooltip} ${localizations.formatMonthYear(_nextMonthDate)}',
// onPressed: _isDisplayingLastMonth ? null : _handleNextMonth,
// ),
// ),
// ),
// ),
// ],
// ),
// );
// }
//
// @override
// void dispose() {
// _timer?.cancel();
// _chevronOpacityController?.dispose();
// _dayPickerController?.dispose();
// super.dispose();
// }
// }
//
// // Defines semantic traversal order of the top-level widgets inside the month
// // picker.
// class _MonthPickerSortKey extends OrdinalSortKey {
// const _MonthPickerSortKey(double order) : super(order);
//
// static const _MonthPickerSortKey previousMonth = _MonthPickerSortKey(1.0);
// static const _MonthPickerSortKey nextMonth = _MonthPickerSortKey(2.0);
// static const _MonthPickerSortKey calendar = _MonthPickerSortKey(3.0);
// }
//
// /// A scrollable list of years to allow picking a year.
// ///
// /// The year picker widget is rarely used directly. Instead, consider using
// /// [showDatePicker], which creates a date picker dialog.
// ///
// /// Requires one of its ancestors to be a [Material] widget.
// ///
// /// See also:
// ///
// /// * [showDatePicker], which shows a dialog that contains a material design
// /// date picker.
// /// * [showTimePicker], which shows a dialog that contains a material design
// /// time picker.
// class YearPicker extends StatefulWidget {
// /// Creates a year picker.
// ///
// /// The [selectedDate] and [onChanged] arguments must not be null. The
// /// [lastDate] must be after the [firstDate].
// ///
// /// Rarely used directly. Instead, typically used as part of the dialog shown
// /// by [showDatePicker].
// YearPicker({
// Key key,
// @required this.selectedDate,
// @required this.onChanged,
// @required this.firstDate,
// @required this.lastDate,
// this.era = EraMode.CHRIST_YEAR,
// this.fontFamily,
// this.dragStartBehavior = DragStartBehavior.start,
// }) : assert(selectedDate != null),
// assert(onChanged != null),
// assert(!firstDate.isAfter(lastDate)),
// super(key: key);
//
// /// The currently selected date.
// ///
// /// This date is highlighted in the picker.
// final DateTime selectedDate;
//
// /// Called when the user picks a year.
// final ValueChanged<DateTime> onChanged;
//
// /// The earliest date the user is permitted to pick.
// final DateTime firstDate;
//
// /// The latest date the user is permitted to pick.
// final DateTime lastDate;
//
// /// {@macro flutter.widgets.scrollable.dragStartBehavior}
// final DragStartBehavior dragStartBehavior;
//
// /// Era
// final EraMode era;
//
// /// Font
// final String fontFamily;
//
// @override
// _YearPickerState createState() => _YearPickerState();
// }
//
// class _YearPickerState extends State<YearPicker> {
// static const double _itemExtent = 50.0;
// ScrollController scrollController;
//
// @override
// void initState() {
// super.initState();
// scrollController = ScrollController(
// // Move the initial scroll position to the currently selected date's year.
// initialScrollOffset:
// (widget.selectedDate.year - widget.firstDate.year) * _itemExtent,
// );
// }
//
// @override
// Widget build(BuildContext context) {
// assert(debugCheckHasMaterial(context));
// final ThemeData themeData = Theme.of(context);
// final TextStyle style = themeData.textTheme.bodyText2
// .copyWith(fontFamily: widget.fontFamily, fontWeight: FontWeight.w700);
// return ConstrainedBox(
// constraints: BoxConstraints(maxHeight: 300),
// child: ListView.builder(
// physics: BouncingScrollPhysics(),
// dragStartBehavior: widget.dragStartBehavior,
// controller: scrollController,
// itemExtent: _itemExtent,
// itemCount: widget.lastDate.year - widget.firstDate.year + 1,
// itemBuilder: (BuildContext context, int index) {
// final int year = widget.firstDate.year + index;
// final bool isSelected = year == widget.selectedDate.year;
// final TextStyle itemStyle = isSelected
// ? themeData.textTheme.headline5.copyWith(
// color: themeData.accentColor,
// fontFamily: widget.fontFamily,
// fontWeight: FontWeight.w900)
// : style;
// return InkWell(
// key: ValueKey<int>(year),
// onTap: () {
// widget.onChanged(DateTime(
// year,
// widget.selectedDate.month,
// widget.selectedDate.day,
// ));
// },
// child: Center(
// child: Semantics(
// selected: isSelected,
// child: Text(
// "${calculateYearEra(widget.era, year)}",
// style: itemStyle,
// ),
// ),
// ),
// );
// },
// ),
// );
// }
// }
//
// class DatePickerDialog extends StatefulWidget {
// const DatePickerDialog({
// Key key,
// this.initialDate,
// this.yearSelectAllowed,
// this.firstDate,
// this.lastDate,
// this.selectableDayPredicate,
// this.initialDatePickerMode,
// this.era,
// this.locale,
// this.borderRadius,
// this.imageHeader,
// this.description = "",
// this.fontFamily,
// this.negativeBtn,
// this.positiveBtn,
// this.leftBtn,
// this.onLeftBtn,
// }) : super(key: key);
//
// final DateTime initialDate;
// final DateTime firstDate;
// final DateTime lastDate;
// final SelectableDayPredicate selectableDayPredicate;
// final DatePickerMode initialDatePickerMode;
// final bool yearSelectAllowed;
//
// /// Custom era year.
// final EraMode era;
// final Locale locale;
//
// /// Border
// final double borderRadius;
//
// /// Header;
// final ImageProvider imageHeader;
// final String description;
//
// /// Font
// final String fontFamily;
//
// final String negativeBtn;
// final String positiveBtn;
// final String leftBtn;
// final VoidCallback onLeftBtn;
//
// @override
// _DatePickerDialogState createState() => _DatePickerDialogState();
// }
//
// class _DatePickerDialogState extends State<DatePickerDialog> {
// @override
// void initState() {
// super.initState();
// _selectedDate = widget.initialDate;
// _mode = widget.initialDatePickerMode;
// }
//
// bool _announcedInitialDate = false;
//
// MaterialLocalizations localizations;
// TextDirection textDirection;
//
// @override
// void didChangeDependencies() {
// super.didChangeDependencies();
// localizations = MaterialLocalizations.of(context);
// textDirection = Directionality.of(context);
// if (!_announcedInitialDate) {
// _announcedInitialDate = true;
// SemanticsService.announce(
// localizations.formatFullDate(_selectedDate),
// textDirection,
// );
// }
// }
//
// DateTime _selectedDate;
// DatePickerMode _mode;
// final GlobalKey _pickerKey = GlobalKey();
//
// void _vibrate() {
// HapticFeedback.vibrate();
// }
//
// void _handleModeChanged(DatePickerMode mode) {
// _vibrate();
// setState(() {
// _mode = mode;
// if (_mode == DatePickerMode.day) {
// SemanticsService.announce(
// localizations.formatMonthYear(_selectedDate),
// textDirection,
// );
// } else {
// SemanticsService.announce(
// localizations.formatYear(_selectedDate),
// textDirection,
// );
// }
// });
// }
//
// void _handleYearChanged(DateTime value) {
// if (value.isBefore(widget.firstDate)) {
// value = widget.firstDate;
// } else if (value.isAfter(widget.lastDate)) {
// value = widget.lastDate;
// }
// if (value == _selectedDate) return;
//
// _vibrate();
// setState(() {
// _mode = DatePickerMode.day;
// _selectedDate = value;
// });
// }
//
// void _handleDayChanged(DateTime value) {
// _vibrate();
// setState(() {
// _selectedDate = value;
// });
// }
//
// void _handleOk() {
// Navigator.of(context).pop(_selectedDate);
// }
//
// Widget _buildPicker() {
// assert(_mode != null);
// switch (_mode) {
// case DatePickerMode.day:
// return MonthPicker(
// key: _pickerKey,
// selectedDate: _selectedDate,
// onChanged: _handleDayChanged,
// firstDate: widget.firstDate,
// lastDate: widget.lastDate,
// era: widget.era,
// locale: widget.locale,
// selectableDayPredicate: widget.selectableDayPredicate,
// fontFamily: widget.fontFamily,
// );
// case DatePickerMode.year:
// return YearPicker(
// key: _pickerKey,
// selectedDate: _selectedDate,
// onChanged: _handleYearChanged,
// firstDate: widget.firstDate,
// lastDate: widget.lastDate,
// era: widget.era,
// fontFamily: widget.fontFamily,
// );
// }
// return null;
// }
//
// @override
// Widget build(BuildContext context) {
// final ThemeData theme = Theme.of(context);
// final Widget picker = _buildPicker();
//
// final Widget actions = ButtonActions(onPositive: _handleOk);
//
// final Dialog dialog = Dialog(
// child: OrientationBuilder(
// builder: (BuildContext context, Orientation orientation) {
// assert(orientation != null);
// final Widget header = _DatePickerHeader(
// selectedDate: _selectedDate,
// yearSelectAllowed: widget.yearSelectAllowed ?? true,
// mode: _mode,
// onModeChanged: _handleModeChanged,
// orientation: orientation,
// era: widget.era,
// borderRadius: widget.borderRadius,
// imageHeader: widget.imageHeader,
// description: widget.description,
// fontFamily: widget.fontFamily,
// );
// switch (orientation) {
// case Orientation.portrait:
// return Container(
// decoration: BoxDecoration(
// color: theme.dialogBackgroundColor,
// borderRadius: BorderRadius.circular(widget.borderRadius),
// ),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.stretch,
// children: <Widget>[
// header,
// Flexible(child: picker),
// actions,
// ],
// ),
// );
// case Orientation.landscape:
// return Container(
// decoration: BoxDecoration(
// color: theme.dialogBackgroundColor,
// borderRadius: BorderRadius.circular(widget.borderRadius),
// ),
// child: Row(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.stretch,
// children: <Widget>[
// Flexible(child: header),
// Flexible(
// flex: 2,
// // have the picker take up 2/3 of the dialog width
// child: Column(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.stretch,
// children: <Widget>[
// Flexible(child: picker),
// actions,
// ],
// ),
// ),
// ],
// ),
// );
// }
// return null;
// }),
// );
//
// return Theme(
// data: theme.copyWith(dialogBackgroundColor: Colors.transparent),
// child: dialog,
// );
// }
// }
//
// /// Signature for predicating dates for enabled date selections.
// ///
// /// See [showDatePicker].
// typedef SelectableDayPredicate = bool Function(DateTime day);
//
// /// Shows a dialog containing a material design date picker.
// ///
// /// The returned [Future] resolves to the date selected by the user when the
// /// user closes the dialog. If the user cancels the dialog, null is returned.
// ///
// /// An optional [selectableDayPredicate] function can be passed in to customize
// /// the days to enable for selection. If provided, only the days that
// /// [selectableDayPredicate] returned true for will be selectable.
// ///
// /// An optional [initialDatePickerMode] argument can be used to display the
// /// date picker initially in the year or month+day picker mode. It defaults
// /// to month+day, and must not be null.
// ///
// /// An optional [locale] argument can be used to set the locale for the date
// /// picker. It defaults to the ambient locale provided by [Localizations].
// ///
// /// An optional [textDirection] argument can be used to set the text direction
// /// (RTL or LTR) for the date picker. It defaults to the ambient text direction
// /// provided by [Directionality]. If both [locale] and [textDirection] are not
// /// null, [textDirection] overrides the direction chosen for the [locale].
// ///
// /// The [context] argument is passed to [showDialog], the documentation for
// /// which discusses how it is used.
// ///
// /// The [builder] parameter can be used to wrap the dialog widget
// /// to add inherited widgets like [Theme].
// ///
// /// {@tool sample}
// /// Show a date picker with the dark theme.
// ///
// /// ```dart
// /// Future<DateTime> selectedDate = showDatePicker(
// /// context: context,
// /// initialDate: DateTime.now(),
// /// firstDate: DateTime(2018),
// /// lastDate: DateTime(2030),
// /// builder: (BuildContext context, Widget child) {
// /// return Theme(
// /// data: ThemeData.dark(),
// /// child: child,
// /// );
// /// },
// /// );
// /// ```
// /// {@end-tool}
// ///
// /// The [context], [initialDate], [firstDate], and [lastDate] parameters must
// /// not be null.
// ///
// /// See also:
// ///
// /// * [showTimePicker], which shows a dialog that contains a material design
// /// time picker.
// /// * [DayPicker], which displays the days of a given month and allows
// /// choosing a day.
// /// * [MonthPicker], which displays a scrollable list of months to allow
// /// picking a month.
// /// * [YearPicker], which displays a scrollable list of years to allow picking
// /// a year.
// ///
//
// Future<DateTime> showRoundedDatePicker(
// {@required BuildContext context,
// DateTime initialDate,
// DateTime firstDate,
// DateTime lastDate,
// SelectableDayPredicate selectableDayPredicate,
// DatePickerMode initialDatePickerMode = DatePickerMode.day,
// Locale locale,
// TextDirection textDirection,
// ThemeData theme,
// double borderRadius = 16,
// EraMode era = EraMode.CHRIST_YEAR,
// ImageProvider imageHeader,
// String description = "",
// String fontFamily,
// bool barrierDismissible = false,
// Color background = Colors.transparent,
// String negativeBtn,
// String positiveBtn,
// String leftBtn,
// VoidCallback onLeftBtn,
// bool yearSelectAllowed}) async {
// initialDate ??= DateTime.now();
// firstDate ??= DateTime(initialDate.year - 1);
// lastDate ??= DateTime(initialDate.year + 1);
// theme ??= ThemeData();
//
// assert(initialDate != null);
// assert(firstDate != null);
// assert(lastDate != null);
// assert(
// !initialDate.isBefore(firstDate),
// 'initialDate must be on or after firstDate',
// );
// assert(
// !initialDate.isAfter(lastDate),
// 'initialDate must be on or before lastDate',
// );
// assert(
// !firstDate.isAfter(lastDate),
// 'lastDate must be on or after firstDate',
// );
// assert(
// selectableDayPredicate == null || selectableDayPredicate(initialDate),
// 'Provided initialDate must satisfy provided selectableDayPredicate',
// );
// assert(
// initialDatePickerMode != null,
// 'initialDatePickerMode must not be null',
// );
// assert(
// (onLeftBtn != null && leftBtn != null) || onLeftBtn == null,
// "If you provide onLeftBtn, you must provide leftBtn",
// );
// assert(context != null);
// assert(debugCheckHasMaterialLocalizations(context));
//
// Widget child = GestureDetector(
// onTap: () {
// if (!barrierDismissible) {
// Navigator.pop(context);
// }
// },
// child: Container(
// color: background,
// child: GestureDetector(
// onTap: () {
// //
// },
// child: DatePickerDialog(
// initialDate: initialDate,
// firstDate: firstDate,
// lastDate: lastDate,
// yearSelectAllowed: yearSelectAllowed,
// selectableDayPredicate: selectableDayPredicate,
// initialDatePickerMode: initialDatePickerMode,
// era: era,
// locale: locale,
// borderRadius: borderRadius,
// imageHeader: imageHeader,
// description: description,
// fontFamily: fontFamily,
// negativeBtn: negativeBtn,
// positiveBtn: positiveBtn,
// leftBtn: leftBtn,
// onLeftBtn: onLeftBtn,
// ),
// ),
// ),
// );
//
// if (textDirection != null) {
// child = Directionality(
// textDirection: textDirection,
// child: child,
// );
// }
//
// if (locale != null) {
// child = Localizations.override(
// context: context,
// locale: locale,
// child: child,
// );
// }
//
// return await showDialog<DateTime>(
// context: context,
// barrierDismissible: barrierDismissible,
// builder: (_) => Theme(data: theme, child: child),
// );
// }