| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 |
- import 'package:flutter_datetime_picker/src/date_format.dart';
- import 'package:flutter_datetime_picker/src/i18n_model.dart';
- import 'datetime_util.dart';
- import 'dart:math';
- //interface for picker data model
- abstract class BasePickerModel {
- //a getter method for left column data, return null to end list
- String leftStringAtIndex(int index);
- //a getter method for middle column data, return null to end list
- String middleStringAtIndex(int index);
- //a getter method for right column data, return null to end list
- String rightStringAtIndex(int index);
- //set selected left index
- void setLeftIndex(int index);
- //set selected middle index
- void setMiddleIndex(int index);
- //set selected right index
- void setRightIndex(int index);
- //return current left index
- int currentLeftIndex();
- //return current middle index
- int currentMiddleIndex();
- //return current right index
- int currentRightIndex();
- //return final time
- DateTime finalTime();
- //return left divider string
- String leftDivider();
- //return right divider string
- String rightDivider();
- //layout proportions for 3 columns
- List<int> layoutProportions();
- }
- //a base class for picker data model
- class CommonPickerModel extends BasePickerModel {
- List<String> leftList;
- List<String> middleList;
- List<String> rightList;
- DateTime currentTime;
- int _currentLeftIndex;
- int _currentMiddleIndex;
- int _currentRightIndex;
- LocaleType locale;
- CommonPickerModel({this.currentTime, locale}) : this.locale = locale ?? LocaleType.en;
- @override
- String leftStringAtIndex(int index) {
- return null;
- }
- @override
- String middleStringAtIndex(int index) {
- return null;
- }
- @override
- String rightStringAtIndex(int index) {
- return null;
- }
- @override
- int currentLeftIndex() {
- return _currentLeftIndex;
- }
- @override
- int currentMiddleIndex() {
- return _currentMiddleIndex;
- }
- @override
- int currentRightIndex() {
- return _currentRightIndex;
- }
- @override
- void setLeftIndex(int index) {
- _currentLeftIndex = index;
- }
- @override
- void setMiddleIndex(int index) {
- _currentMiddleIndex = index;
- }
- @override
- void setRightIndex(int index) {
- _currentRightIndex = index;
- }
- @override
- String leftDivider() {
- return "";
- }
- @override
- String rightDivider() {
- return "";
- }
- @override
- List<int> layoutProportions() {
- return [1, 1, 1];
- }
- @override
- DateTime finalTime() {
- return null;
- }
- }
- //a date picker model
- class DatePickerModel extends CommonPickerModel {
- DateTime maxTime;
- DateTime minTime;
- DatePickerModel({DateTime currentTime, DateTime maxTime, DateTime minTime, LocaleType locale})
- : super(locale: locale) {
- this.maxTime = maxTime ?? DateTime(2049, 12, 31);
- this.minTime = minTime ?? DateTime(1970, 1, 1);
- currentTime = currentTime ?? DateTime.now();
- if (currentTime != null) {
- if (currentTime.compareTo(this.maxTime) > 0) {
- currentTime = this.maxTime;
- } else if (currentTime.compareTo(this.minTime) < 0) {
- currentTime = this.minTime;
- }
- }
- this.currentTime = currentTime;
- _fillLeftLists();
- _fillMiddleLists();
- _fillRightLists();
- int minMonth = _minMonthOfCurrentYear();
- int minDay = _minDayOfCurrentMonth();
- _currentLeftIndex = this.currentTime.year - this.minTime.year;
- _currentMiddleIndex = this.currentTime.month - minMonth;
- _currentRightIndex = this.currentTime.day - minDay;
- }
- void _fillLeftLists() {
- this.leftList = List.generate(maxTime.year - minTime.year + 1, (int index) {
- // print('LEFT LIST... ${minTime.year + index}${_localeYear()}');
- return '${minTime.year + index}${_localeYear()}';
- });
- }
- int _maxMonthOfCurrentYear() {
- return currentTime.year == maxTime.year ? maxTime.month : 12;
- }
- int _minMonthOfCurrentYear() {
- return currentTime.year == minTime.year ? minTime.month : 1;
- }
- int _maxDayOfCurrentMonth() {
- int dayCount = calcDateCount(currentTime.year, currentTime.month);
- return currentTime.year == maxTime.year && currentTime.month == maxTime.month
- ? maxTime.day
- : dayCount;
- }
- int _minDayOfCurrentMonth() {
- return currentTime.year == minTime.year && currentTime.month == minTime.month ? minTime.day : 1;
- }
- void _fillMiddleLists() {
- int minMonth = _minMonthOfCurrentYear();
- int maxMonth = _maxMonthOfCurrentYear();
- this.middleList = List.generate(maxMonth - minMonth + 1, (int index) {
- return '${_localeMonth(minMonth + index)}';
- });
- }
- void _fillRightLists() {
- int maxDay = _maxDayOfCurrentMonth();
- int minDay = _minDayOfCurrentMonth();
- this.rightList = List.generate(maxDay - minDay + 1, (int index) {
- return '${minDay + index}${_localeDay()}';
- });
- }
- @override
- void setLeftIndex(int index) {
- super.setLeftIndex(index);
- //adjust middle
- int destYear = index + minTime.year;
- int minMonth = _minMonthOfCurrentYear();
- DateTime newTime;
- //change date time
- if (currentTime.month == 2 && currentTime.day == 29) {
- newTime = currentTime.isUtc
- ? DateTime.utc(
- destYear,
- currentTime.month,
- calcDateCount(destYear, 2),
- )
- : DateTime(
- destYear,
- currentTime.month,
- calcDateCount(destYear, 2),
- );
- } else {
- newTime = currentTime.isUtc
- ? DateTime.utc(
- destYear,
- currentTime.month,
- currentTime.day,
- )
- : DateTime(
- destYear,
- currentTime.month,
- currentTime.day,
- );
- }
- //min/max check
- if (newTime.isAfter(maxTime)) {
- currentTime = maxTime;
- } else if (newTime.isBefore(minTime)) {
- currentTime = minTime;
- } else {
- currentTime = newTime;
- }
- _fillMiddleLists();
- _fillRightLists();
- minMonth = _minMonthOfCurrentYear();
- int minDay = _minDayOfCurrentMonth();
- _currentMiddleIndex = currentTime.month - minMonth;
- _currentRightIndex = currentTime.day - minDay;
- }
- @override
- void setMiddleIndex(int index) {
- super.setMiddleIndex(index);
- //adjust right
- int minMonth = _minMonthOfCurrentYear();
- int destMonth = minMonth + index;
- DateTime newTime;
- //change date time
- int dayCount = calcDateCount(currentTime.year, destMonth);
- newTime = currentTime.isUtc
- ? DateTime.utc(
- currentTime.year,
- destMonth,
- currentTime.day <= dayCount ? currentTime.day : dayCount,
- )
- : DateTime(
- currentTime.year,
- destMonth,
- currentTime.day <= dayCount ? currentTime.day : dayCount,
- );
- //min/max check
- if (newTime.isAfter(maxTime)) {
- currentTime = maxTime;
- } else if (newTime.isBefore(minTime)) {
- currentTime = minTime;
- } else {
- currentTime = newTime;
- }
- _fillRightLists();
- int minDay = _minDayOfCurrentMonth();
- _currentRightIndex = currentTime.day - minDay;
- }
- @override
- void setRightIndex(int index) {
- super.setRightIndex(index);
- int minDay = _minDayOfCurrentMonth();
- currentTime = currentTime.isUtc
- ? DateTime.utc(
- currentTime.year,
- currentTime.month,
- minDay + index,
- )
- : DateTime(
- currentTime.year,
- currentTime.month,
- minDay + index,
- );
- }
- @override
- String leftStringAtIndex(int index) {
- if (index >= 0 && index < leftList.length) {
- return leftList[index];
- } else {
- return null;
- }
- }
- @override
- String middleStringAtIndex(int index) {
- if (index >= 0 && index < middleList.length) {
- return middleList[index];
- } else {
- return null;
- }
- }
- @override
- String rightStringAtIndex(int index) {
- if (index >= 0 && index < rightList.length) {
- return rightList[index];
- } else {
- return null;
- }
- }
- String _localeYear() {
- if (locale == LocaleType.zh || locale == LocaleType.jp) {
- return '年';
- } else if (locale == LocaleType.ko) {
- return '년';
- } else {
- return '';
- }
- }
- String _localeMonth(int month) {
- if (locale == LocaleType.zh || locale == LocaleType.jp) {
- return '$month月';
- } else if (locale == LocaleType.ko) {
- return '$month월';
- } else {
- List monthStrings = i18nObjInLocale(locale)['monthLong'];
- return monthStrings[month - 1];
- }
- }
- String _localeDay() {
- if (locale == LocaleType.zh || locale == LocaleType.jp) {
- return '日';
- } else if (locale == LocaleType.ko) {
- return '일';
- } else {
- return '';
- }
- }
- @override
- DateTime finalTime() {
- return currentTime;
- }
- }
- //a time picker model
- class TimePickerModel extends CommonPickerModel {
- bool showSecondsColumn;
- TimePickerModel({DateTime currentTime, LocaleType locale, this.showSecondsColumn: true})
- : super(locale: locale) {
- this.currentTime = currentTime ?? DateTime.now();
- _currentLeftIndex = this.currentTime.hour;
- _currentMiddleIndex = this.currentTime.minute;
- _currentRightIndex = this.currentTime.second;
- }
- @override
- String leftStringAtIndex(int index) {
- if (index >= 0 && index < 24) {
- return digits(index, 2);
- } else {
- return null;
- }
- }
- @override
- String middleStringAtIndex(int index) {
- if (index >= 0 && index < 60) {
- return digits(index, 2);
- } else {
- return null;
- }
- }
- @override
- String rightStringAtIndex(int index) {
- if (index >= 0 && index < 60) {
- return digits(index, 2);
- } else {
- return null;
- }
- }
- @override
- String leftDivider() {
- return ":";
- }
- @override
- String rightDivider() {
- if (showSecondsColumn)
- return ":";
- else
- return "";
- }
- @override
- List<int> layoutProportions() {
- if (showSecondsColumn)
- return [1, 1, 1];
- else
- return [1, 1, 0];
- }
- @override
- DateTime finalTime() {
- return currentTime.isUtc
- ? DateTime.utc(currentTime.year, currentTime.month, currentTime.day, _currentLeftIndex,
- _currentMiddleIndex, _currentRightIndex)
- : DateTime(currentTime.year, currentTime.month, currentTime.day, _currentLeftIndex,
- _currentMiddleIndex, _currentRightIndex);
- }
- }
- //a time picker model
- class Time12hPickerModel extends CommonPickerModel {
- Time12hPickerModel({DateTime currentTime, LocaleType locale}) : super(locale: locale) {
- this.currentTime = currentTime ?? DateTime.now();
- _currentLeftIndex = this.currentTime.hour % 12;
- _currentMiddleIndex = this.currentTime.minute;
- _currentRightIndex = this.currentTime.hour < 12 ? 0 : 1;
- }
- @override
- String leftStringAtIndex(int index) {
- if (index >= 0 && index < 12) {
- if (index == 0) {
- return digits(12, 2);
- } else {
- return digits(index, 2);
- }
- } else {
- return null;
- }
- }
- @override
- String middleStringAtIndex(int index) {
- if (index >= 0 && index < 60) {
- return digits(index, 2);
- } else {
- return null;
- }
- }
- @override
- String rightStringAtIndex(int index) {
- if (index == 0) {
- return i18nObjInLocale(this.locale)["am"];
- } else if (index == 1) {
- return i18nObjInLocale(this.locale)["pm"];
- } else {
- return null;
- }
- }
- @override
- String leftDivider() {
- return ":";
- }
- @override
- String rightDivider() {
- return ":";
- }
- @override
- List<int> layoutProportions() {
- return [1, 1, 1];
- }
- @override
- DateTime finalTime() {
- int hour = _currentLeftIndex + 12 * _currentRightIndex;
- return currentTime.isUtc
- ? DateTime.utc(
- currentTime.year, currentTime.month, currentTime.day, hour, _currentMiddleIndex, 0)
- : DateTime(
- currentTime.year, currentTime.month, currentTime.day, hour, _currentMiddleIndex, 0);
- }
- }
- // a date&time picker model
- class DateTimePickerModel extends CommonPickerModel {
- DateTime maxTime;
- DateTime minTime;
- DateTimePickerModel({DateTime currentTime, DateTime maxTime, DateTime minTime, LocaleType locale})
- : super(locale: locale) {
- if (currentTime != null) {
- this.currentTime = currentTime;
- if (maxTime != null &&
- (currentTime.isBefore(maxTime) || currentTime.isAtSameMomentAs(maxTime))) {
- this.maxTime = maxTime;
- }
- if (minTime != null &&
- (currentTime.isAfter(minTime) || currentTime.isAtSameMomentAs(minTime))) {
- this.minTime = minTime;
- }
- } else {
- this.maxTime = maxTime;
- this.minTime = minTime;
- var now = DateTime.now();
- if (this.minTime != null && this.minTime.isAfter(now)) {
- this.currentTime = this.minTime;
- } else if (this.maxTime != null && this.maxTime.isBefore(now)) {
- this.currentTime = this.maxTime;
- } else {
- this.currentTime = now;
- }
- }
- if (this.minTime != null && this.maxTime != null && this.maxTime.isBefore(this.minTime)) {
- // invalid
- this.minTime = null;
- this.maxTime = null;
- }
- _currentLeftIndex = 0;
- _currentMiddleIndex = this.currentTime.hour;
- _currentRightIndex = this.currentTime.minute;
- if (this.minTime != null && isAtSameDay(this.minTime, this.currentTime)) {
- _currentMiddleIndex = this.currentTime.hour - this.minTime.hour;
- if (_currentMiddleIndex == 0) {
- _currentRightIndex = this.currentTime.minute - this.minTime.minute;
- }
- }
- }
- bool isAtSameDay(DateTime day1, DateTime day2) {
- return day1 != null &&
- day2 != null &&
- day1.difference(day2).inDays == 0 &&
- day1.day == day2.day;
- }
- @override
- void setLeftIndex(int index) {
- // TODO: implement setLeftIndex
- super.setLeftIndex(index);
- DateTime time = currentTime.add(Duration(days: index));
- if (isAtSameDay(minTime, time)) {
- var index = min(24 - minTime.hour - 1, _currentMiddleIndex);
- this.setMiddleIndex(index);
- } else if (isAtSameDay(maxTime, time)) {
- var index = min(maxTime.hour, _currentMiddleIndex);
- this.setMiddleIndex(index);
- }
- }
- @override
- void setMiddleIndex(int index) {
- // TODO: implement setMiddleIndex
- super.setMiddleIndex(index);
- DateTime time = currentTime.add(Duration(days: _currentLeftIndex));
- if (isAtSameDay(minTime, time) && index == 0) {
- var maxIndex = 60 - minTime.minute - 1;
- if (_currentRightIndex > maxIndex) {
- _currentRightIndex = maxIndex;
- }
- } else if (isAtSameDay(maxTime, time) && _currentMiddleIndex == maxTime.hour) {
- var maxIndex = maxTime.minute;
- if (_currentRightIndex > maxIndex) {
- _currentRightIndex = maxIndex;
- }
- }
- }
- @override
- String leftStringAtIndex(int index) {
- DateTime time = currentTime.add(Duration(days: index));
- if (minTime != null && time.isBefore(minTime) && !isAtSameDay(minTime, time)) {
- return null;
- } else if (maxTime != null && time.isAfter(maxTime) && !isAtSameDay(maxTime, time)) {
- return null;
- }
- return formatDate(time, [ymdw], locale);
- }
- @override
- String middleStringAtIndex(int index) {
- if (index >= 0 && index < 24) {
- DateTime time = currentTime.add(Duration(days: _currentLeftIndex));
- if (isAtSameDay(minTime, time)) {
- if (index >= 0 && index < 24 - minTime.hour) {
- return digits(minTime.hour + index, 2);
- } else {
- return null;
- }
- } else if (isAtSameDay(maxTime, time)) {
- if (index >= 0 && index <= maxTime.hour) {
- return digits(index, 2);
- } else {
- return null;
- }
- }
- return digits(index, 2);
- }
- return null;
- }
- @override
- String rightStringAtIndex(int index) {
- if (index >= 0 && index < 60) {
- DateTime time = currentTime.add(Duration(days: _currentLeftIndex));
- if (isAtSameDay(minTime, time) && _currentMiddleIndex == 0) {
- if (index >= 0 && index < 60 - minTime.minute) {
- return digits(minTime.minute + index, 2);
- } else {
- return null;
- }
- } else if (isAtSameDay(maxTime, time) && _currentMiddleIndex >= maxTime.hour) {
- if (index >= 0 && index <= maxTime.minute) {
- return digits(index, 2);
- } else {
- return null;
- }
- }
- return digits(index, 2);
- }
- return null;
- }
- @override
- DateTime finalTime() {
- DateTime time = currentTime.add(Duration(days: _currentLeftIndex));
- var hour = _currentMiddleIndex;
- var minute = _currentRightIndex;
- if (isAtSameDay(minTime, time)) {
- hour += minTime.hour;
- if (minTime.hour == hour) {
- minute += minTime.minute;
- }
- }
- return currentTime.isUtc
- ? DateTime.utc(time.year, time.month, time.day, hour, minute)
- : DateTime(time.year, time.month, time.day, hour, minute);
- }
- @override
- List<int> layoutProportions() {
- return [4, 1, 1];
- }
- @override
- String rightDivider() {
- return ':';
- }
- }
|