Line data Source code
1 : import 'package:flutter/material.dart';
2 :
3 : import 'date_picker_keys.dart';
4 : import 'day_based_changable_picker.dart';
5 : import 'day_picker_selection.dart';
6 : import 'day_type.dart';
7 : import 'i_selectable_picker.dart';
8 : import 'styles/date_picker_styles.dart';
9 : import 'styles/event_decoration.dart';
10 : import 'styles/layout_settings.dart';
11 : import 'utils.dart';
12 :
13 : /// Date picker for selection one day.
14 : class DayPicker<T extends Object> extends StatelessWidget {
15 0 : DayPicker._(
16 : {Key? key,
17 : required this.onChanged,
18 : required this.firstDate,
19 : required this.lastDate,
20 : required this.selectionLogic,
21 : required this.selection,
22 : this.initiallyShowDate,
23 : this.datePickerLayoutSettings = const DatePickerLayoutSettings(),
24 : this.datePickerStyles,
25 : this.datePickerKeys,
26 : this.selectableDayPredicate,
27 : this.eventDecorationBuilder,
28 : this.onMonthChanged})
29 0 : : super(key: key);
30 :
31 : /// Creates a day picker where only one single day can be selected.
32 : ///
33 : /// See also:
34 : /// * [DayPicker.multi] - day picker where many single days can be selected.
35 0 : static DayPicker<DateTime> single(
36 : {Key? key,
37 : required DateTime selectedDate,
38 : required ValueChanged<DateTime> onChanged,
39 : required DateTime firstDate,
40 : required DateTime lastDate,
41 : DatePickerLayoutSettings datePickerLayoutSettings =
42 : const DatePickerLayoutSettings(),
43 : DateTime? initiallyShowDate,
44 : DatePickerRangeStyles? datePickerStyles,
45 : DatePickerKeys? datePickerKeys,
46 : SelectableDayPredicate? selectableDayPredicate,
47 : EventDecorationBuilder? eventDecorationBuilder,
48 : ValueChanged<DateTime>? onMonthChanged}) {
49 0 : final startOfTheFirstDate = DatePickerUtils.startOfTheDay(firstDate);
50 0 : final endOfTheLastDate = DatePickerUtils.endOfTheDay(lastDate);
51 0 : final startOfTheSelectedDate = DatePickerUtils.startOfTheDay(selectedDate);
52 : final startOfTheInitiallyShowDate = initiallyShowDate == null
53 : ? null
54 0 : : DatePickerUtils.startOfTheDay(initiallyShowDate);
55 :
56 0 : assert(!startOfTheFirstDate.isAfter(endOfTheLastDate));
57 0 : assert(!endOfTheLastDate.isBefore(startOfTheFirstDate));
58 0 : assert(!startOfTheSelectedDate.isBefore(startOfTheFirstDate));
59 0 : assert(!startOfTheSelectedDate.isAfter(endOfTheLastDate));
60 0 : assert(startOfTheInitiallyShowDate == null ||
61 0 : !startOfTheInitiallyShowDate.isAfter(endOfTheLastDate));
62 0 : assert(startOfTheInitiallyShowDate == null ||
63 0 : !startOfTheInitiallyShowDate.isBefore(startOfTheFirstDate));
64 :
65 0 : final selection = DayPickerSingleSelection(startOfTheSelectedDate);
66 0 : final selectionLogic = DaySelectable(
67 : startOfTheSelectedDate,
68 : startOfTheFirstDate,
69 : endOfTheLastDate,
70 : selectableDayPredicate: selectableDayPredicate,
71 : );
72 :
73 0 : return DayPicker<DateTime>._(
74 : onChanged: onChanged,
75 : firstDate: startOfTheFirstDate,
76 : lastDate: endOfTheLastDate,
77 : initiallyShowDate: startOfTheInitiallyShowDate,
78 : selectionLogic: selectionLogic,
79 : selection: selection,
80 : eventDecorationBuilder: eventDecorationBuilder,
81 : onMonthChanged: onMonthChanged,
82 : selectableDayPredicate: selectableDayPredicate,
83 : datePickerKeys: datePickerKeys,
84 : datePickerStyles: datePickerStyles,
85 : datePickerLayoutSettings: datePickerLayoutSettings,
86 : );
87 : }
88 :
89 : /// Creates a day picker where many single days can be selected.
90 : ///
91 : /// See also:
92 : /// * [DayPicker.single] - day picker where only one single day
93 : /// can be selected.
94 0 : static DayPicker<List<DateTime>> multi(
95 : {Key? key,
96 : required List<DateTime> selectedDates,
97 : required ValueChanged<List<DateTime>> onChanged,
98 : required DateTime firstDate,
99 : required DateTime lastDate,
100 : DatePickerLayoutSettings datePickerLayoutSettings =
101 : const DatePickerLayoutSettings(),
102 : DateTime? initiallyShowDate,
103 : DatePickerRangeStyles? datePickerStyles,
104 : DatePickerKeys? datePickerKeys,
105 : SelectableDayPredicate? selectableDayPredicate,
106 : EventDecorationBuilder? eventDecorationBuilder,
107 : ValueChanged<DateTime>? onMonthChanged}) {
108 0 : final startOfTheFirstDate = DatePickerUtils.startOfTheDay(firstDate);
109 0 : final endOfTheLastDate = DatePickerUtils.endOfTheDay(lastDate);
110 : final startOfTheInitiallyShowDate = initiallyShowDate == null
111 : ? null
112 0 : : DatePickerUtils.startOfTheDay(initiallyShowDate);
113 : final selectedDaysStarts =
114 0 : selectedDates.map(DatePickerUtils.startOfTheDay).toList();
115 :
116 0 : assert(!startOfTheFirstDate.isAfter(endOfTheLastDate));
117 0 : assert(!endOfTheLastDate.isBefore(startOfTheFirstDate));
118 0 : assert(startOfTheInitiallyShowDate == null ||
119 0 : !startOfTheInitiallyShowDate.isAfter(endOfTheLastDate));
120 0 : assert(startOfTheInitiallyShowDate == null ||
121 0 : !startOfTheInitiallyShowDate.isBefore(startOfTheFirstDate));
122 :
123 0 : final selection = DayPickerMultiSelection(selectedDaysStarts);
124 0 : final selectionLogic = DayMultiSelectable(
125 : selectedDaysStarts,
126 : startOfTheFirstDate,
127 : endOfTheLastDate,
128 : selectableDayPredicate: selectableDayPredicate,
129 : );
130 :
131 0 : return DayPicker<List<DateTime>>._(
132 : onChanged: onChanged,
133 : firstDate: startOfTheFirstDate,
134 : lastDate: endOfTheLastDate,
135 : initiallyShowDate: startOfTheInitiallyShowDate,
136 : selectionLogic: selectionLogic,
137 : selection: selection,
138 : eventDecorationBuilder: eventDecorationBuilder,
139 : onMonthChanged: onMonthChanged,
140 : selectableDayPredicate: selectableDayPredicate,
141 : datePickerKeys: datePickerKeys,
142 : datePickerStyles: datePickerStyles,
143 : datePickerLayoutSettings: datePickerLayoutSettings,
144 : );
145 : }
146 :
147 : /// The currently selected date.
148 : ///
149 : /// This date is highlighted in the picker.
150 : final DayPickerSelection selection;
151 :
152 : /// Called when the user picks a day.
153 : final ValueChanged<T> onChanged;
154 :
155 : /// The earliest date the user is permitted to pick.
156 : final DateTime firstDate;
157 :
158 : /// The latest date the user is permitted to pick.
159 : final DateTime lastDate;
160 :
161 : /// Date for defining what month should be shown initially.
162 : ///
163 : /// In case of null earliest of the [selection] will be shown.
164 : final DateTime? initiallyShowDate;
165 :
166 : /// Layout settings what can be customized by user
167 : final DatePickerLayoutSettings datePickerLayoutSettings;
168 :
169 : /// Styles what can be customized by user
170 : final DatePickerRangeStyles? datePickerStyles;
171 :
172 : /// Some keys useful for integration tests
173 : final DatePickerKeys? datePickerKeys;
174 :
175 : /// Function returns if day can be selected or not.
176 : ///
177 : /// If null
178 : final SelectableDayPredicate? selectableDayPredicate;
179 :
180 : /// Builder to get event decoration for each date.
181 : ///
182 : /// All event styles are overriden by selected styles
183 : /// except days with dayType is [DayType.notSelected].
184 : final EventDecorationBuilder? eventDecorationBuilder;
185 :
186 : // Called when the user changes the month.
187 : /// New DateTime object represents first day of new month and 00:00 time.
188 : final ValueChanged<DateTime>? onMonthChanged;
189 :
190 : /// Logic to handle user's selections.
191 : final ISelectablePicker<T> selectionLogic;
192 :
193 0 : @override
194 : // ignore: prefer_expression_function_bodies
195 : Widget build(BuildContext context) {
196 0 : return DayBasedChangeablePicker<T>(
197 0 : selectablePicker: selectionLogic,
198 0 : selection: selection,
199 0 : firstDate: firstDate,
200 0 : lastDate: lastDate,
201 0 : initiallyShownDate: initiallyShowDate,
202 0 : onChanged: onChanged,
203 0 : datePickerLayoutSettings: datePickerLayoutSettings,
204 0 : datePickerStyles: datePickerStyles ?? DatePickerRangeStyles(),
205 0 : datePickerKeys: datePickerKeys,
206 0 : eventDecorationBuilder: eventDecorationBuilder,
207 0 : onMonthChanged: onMonthChanged,
208 : );
209 : }
210 : }
|