1use crate::_private::NonExhaustive;
2use crate::calendar::event::CalOutcome;
3use crate::calendar::selection::{NoSelection, RangeSelection, SingleSelection};
4use crate::calendar::style::CalendarStyle;
5use crate::calendar::{CalendarSelection, first_day_of_month, last_day_of_month};
6use crate::util::{block_size, revert_style};
7use chrono::{Datelike, Days, NaiveDate, Weekday};
8use rat_event::util::MouseFlagsN;
9use rat_focus::{FocusBuilder, FocusFlag, HasFocus};
10use rat_reloc::RelocatableState;
11use ratatui::buffer::Buffer;
12use ratatui::layout::{Alignment, Rect};
13use ratatui::style::Style;
14use ratatui::style::Stylize;
15use ratatui::text::Span;
16use ratatui::widgets::block::Title;
17use ratatui::widgets::{Block, StatefulWidget, Widget};
18use std::cell::RefCell;
19use std::cmp::max;
20use std::collections::HashMap;
21use std::marker::PhantomData;
22use std::rc::Rc;
23
24#[derive(Debug, Clone)]
53pub struct Month<'a, Selection> {
54 start_date: Option<NaiveDate>,
56
57 style: Style,
59 title_style: Option<Style>,
61 title_align: Alignment,
63 weeknum_style: Option<Style>,
65 weekday_style: Option<Style>,
67 day_style: Option<Style>,
69 day_styles: Option<&'a HashMap<NaiveDate, Style>>,
71 select_style: Option<Style>,
73 focus_style: Option<Style>,
75
76 show_month: bool,
78 show_weekdays: bool,
80
81 block: Option<Block<'a>>,
83
84 loc: chrono::Locale,
86
87 phantom: PhantomData<Selection>,
88}
89
90#[derive(Debug)]
92pub struct MonthState<Selection = SingleSelection> {
93 pub area: Rect,
96 pub inner: Rect,
99 pub area_cal: Rect,
102 pub area_days: [Rect; 31],
105 pub area_weeknum: Rect,
108 pub area_weeks: [Rect; 6],
111
112 start_date: NaiveDate,
114
115 pub selection: Rc<RefCell<Selection>>,
118
119 pub container: Option<FocusFlag>,
122
123 pub focus: FocusFlag,
126 pub mouse: MouseFlagsN,
129
130 pub non_exhaustive: NonExhaustive,
131}
132
133impl<Selection> Default for Month<'_, Selection> {
134 fn default() -> Self {
135 Self {
136 start_date: None,
137 style: Default::default(),
138 title_style: Default::default(),
139 title_align: Default::default(),
140 weeknum_style: Default::default(),
141 weekday_style: Default::default(),
142 day_style: Default::default(),
143 day_styles: Default::default(),
144 select_style: Default::default(),
145 focus_style: Default::default(),
146 show_month: true,
147 show_weekdays: true,
148 block: Default::default(),
149 loc: Default::default(),
150 phantom: PhantomData,
151 }
152 }
153}
154
155impl<'a, Selection> Month<'a, Selection> {
156 pub fn new() -> Self {
158 Self::default()
159 }
160
161 #[inline]
164 pub fn date(mut self, s: NaiveDate) -> Self {
165 self.start_date = Some(first_day_of_month(s));
166 self
167 }
168
169 #[inline]
171 pub fn locale(mut self, loc: chrono::Locale) -> Self {
172 self.loc = loc;
173 self
174 }
175
176 #[inline]
178 pub fn show_show_month(mut self) -> Self {
179 self.show_month = true;
180 self
181 }
182
183 #[inline]
185 pub fn show_weekdays(mut self) -> Self {
186 self.show_weekdays = true;
187 self
188 }
189
190 #[inline]
192 pub fn styles(mut self, s: CalendarStyle) -> Self {
193 self.style = s.style;
194 if s.title.is_some() {
195 self.title_style = s.title;
196 }
197 if s.weeknum.is_some() {
198 self.weeknum_style = s.weeknum;
199 }
200 if s.weekday.is_some() {
201 self.weekday_style = s.weekday;
202 }
203 if s.day.is_some() {
204 self.day_style = s.day;
205 }
206 if s.select.is_some() {
207 self.select_style = s.select;
208 }
209 if s.focus.is_some() {
210 self.focus_style = s.focus;
211 }
212 if s.block.is_some() {
213 self.block = s.block;
214 }
215 self.block = self.block.map(|v| v.style(self.style));
216 self
217 }
218
219 pub fn select_style(mut self, style: Style) -> Self {
221 self.select_style = Some(style);
222 self
223 }
224
225 pub fn focus_style(mut self, style: Style) -> Self {
227 self.focus_style = Some(style);
228 self
229 }
230
231 #[inline]
233 pub fn day_style(mut self, s: impl Into<Style>) -> Self {
234 self.day_style = Some(s.into());
235 self
236 }
237
238 #[inline]
240 pub fn day_styles(mut self, styles: &'a HashMap<NaiveDate, Style>) -> Self {
241 self.day_styles = Some(styles);
242 self
243 }
244
245 #[inline]
247 pub fn week_style(mut self, s: impl Into<Style>) -> Self {
248 self.weeknum_style = Some(s.into());
249 self
250 }
251
252 #[inline]
254 pub fn weekday_style(mut self, s: impl Into<Style>) -> Self {
255 self.weekday_style = Some(s.into());
256 self
257 }
258
259 #[inline]
261 pub fn title_style(mut self, s: impl Into<Style>) -> Self {
262 self.title_style = Some(s.into());
263 self
264 }
265
266 #[inline]
268 pub fn title_align(mut self, a: Alignment) -> Self {
269 self.title_align = a;
270 self
271 }
272
273 #[inline]
275 pub fn block(mut self, b: Block<'a>) -> Self {
276 self.block = Some(b);
277 self.block = self.block.map(|v| v.style(self.style));
278 self
279 }
280
281 #[inline]
283 pub fn width(&self) -> u16 {
284 8 * 3 + block_size(&self.block).width
285 }
286
287 #[inline]
290 pub fn height(&self, state: &MonthState<Selection>) -> u16 {
291 let start_date = if let Some(start_date) = self.start_date {
292 start_date
293 } else {
294 state.start_date
295 };
296
297 let r = MonthState::<Selection>::count_weeks(start_date) as u16;
298 let w = if self.show_weekdays { 1 } else { 0 };
299 let b = max(1, block_size(&self.block).height);
300 r + w + b
301 }
302}
303
304impl<'a, Selection> StatefulWidget for &Month<'a, Selection>
305where
306 Selection: CalendarSelection,
307{
308 type State = MonthState<Selection>;
309
310 fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
311 render_ref(self, area, buf, state);
312 }
313}
314
315impl<Selection> StatefulWidget for Month<'_, Selection>
316where
317 Selection: CalendarSelection,
318{
319 type State = MonthState<Selection>;
320
321 fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
322 render_ref(&self, area, buf, state);
323 }
324}
325
326fn render_ref<Selection: CalendarSelection>(
327 widget: &Month<'_, Selection>,
328 area: Rect,
329 buf: &mut Buffer,
330 state: &mut MonthState<Selection>,
331) {
332 state.area = area;
333 if let Some(start_date) = widget.start_date {
334 state.start_date = start_date;
335 }
336
337 let mut day = state.start_date;
338
339 let focus_style = widget.focus_style.unwrap_or(revert_style(widget.style));
340 let select_style = if let Some(select_style) = widget.select_style {
341 if state.is_container_focused() || state.is_focused() {
342 focus_style
343 } else {
344 select_style
345 }
346 } else {
347 if state.is_container_focused() || state.is_focused() {
348 focus_style
349 } else {
350 revert_style(widget.style)
351 }
352 };
353 let day_style = widget.day_style.unwrap_or(widget.style);
354 let week_style = widget.weeknum_style.unwrap_or(widget.style);
355 let weekday_style = widget.weekday_style.unwrap_or(widget.style);
356
357 let title_style = if let Some(title_style) = widget.title_style {
358 title_style
359 } else {
360 widget.style
361 };
362 let title_style = if state.is_focused() {
363 title_style.patch(focus_style)
364 } else {
365 title_style
366 };
367
368 let block = if widget.show_month {
369 if let Some(block) = widget.block.clone() {
370 block
371 .title(Title::from(
372 day.format_localized("%B", widget.loc).to_string(),
373 ))
374 .title_style(title_style)
375 .title_alignment(widget.title_align)
376 } else {
377 Block::new()
378 .style(widget.style)
379 .title(Title::from(
380 day.format_localized("%B", widget.loc).to_string(),
381 ))
382 .title_style(title_style)
383 .title_alignment(widget.title_align)
384 }
385 } else {
386 if let Some(block) = widget.block.clone() {
387 block
388 } else {
389 Block::new().style(widget.style)
390 }
391 };
392 state.inner = block.inner(area);
393 block.render(area, buf);
394
395 let month = day.month();
396 let mut w = 0;
397 let mut x = state.inner.x;
398 let mut y = state.inner.y;
399
400 if widget.show_weekdays {
402 let mut week_0 = day.week(Weekday::Mon).first_day();
403
404 x += 3;
405 buf.set_style(Rect::new(x, y, 3 * 7, 1), weekday_style);
406 for _ in 0..7 {
407 let area = Rect::new(x, y, 2, 1).intersection(state.inner);
408
409 let day_name = week_0.format_localized("%a", widget.loc).to_string();
410 Span::from(format!("{:2} ", day_name)).render(area, buf);
411
412 x += 3;
413 week_0 = week_0 + Days::new(1);
414 }
415 x = state.inner.x;
416 y += 1;
417 }
418
419 for i in 0..31 {
421 state.area_days[i] = Rect::default();
422 }
423 for i in 0..6 {
424 state.area_weeks[i] = Rect::default();
425 }
426 state.area_cal = Rect::new(x + 3, y, 7 * 3, state.week_len() as u16);
427 state.area_weeknum = Rect::new(x, y, 3, state.week_len() as u16);
428
429 state.area_weeks[w] = Rect::new(x, y, 2, 1).intersection(state.inner);
431 Span::from(day.format_localized("%V", widget.loc).to_string())
432 .style(week_style)
433 .render(state.area_weeks[w], buf);
434
435 x += 3;
436
437 for wd in [
438 Weekday::Mon,
439 Weekday::Tue,
440 Weekday::Wed,
441 Weekday::Thu,
442 Weekday::Fri,
443 Weekday::Sat,
444 Weekday::Sun,
445 ] {
446 if day.weekday() != wd {
447 x += 3;
448 } else {
449 let day_style = calc_day_style(widget, state, day, day_style, select_style);
450 state.area_days[day.day0() as usize] = Rect::new(x, y, 2, 1).intersection(state.inner);
451
452 Span::from(day.format_localized("%e", widget.loc).to_string())
453 .style(day_style)
454 .render(state.area_days[day.day0() as usize], buf);
455
456 if wd != Weekday::Sun && state.selection.is_selected(day + Days::new(1)) {
457 let mut gap_area = state.area_days[day.day0() as usize];
458 gap_area.x += 2;
459 gap_area.width = 1;
460 Span::from(" ").style(day_style).render(gap_area, buf);
461 }
462
463 x += 3;
464 day = day + Days::new(1);
465 }
466 }
467
468 w += 1;
469 x = state.inner.x;
470 y += 1;
471
472 while month == day.month() {
473 state.area_weeks[w] = Rect::new(x, y, 2, 1).intersection(state.inner);
474 Span::from(day.format_localized("%V", widget.loc).to_string())
475 .style(week_style)
476 .render(state.area_weeks[w], buf);
477
478 x += 3;
479
480 for wd in [
481 Weekday::Mon,
482 Weekday::Tue,
483 Weekday::Wed,
484 Weekday::Thu,
485 Weekday::Fri,
486 Weekday::Sat,
487 Weekday::Sun,
488 ] {
489 if day.month() == month {
490 let day_style = calc_day_style(widget, state, day, day_style, select_style);
491
492 state.area_days[day.day0() as usize] =
493 Rect::new(x, y, 2, 1).intersection(state.inner);
494
495 Span::from(day.format_localized("%e", widget.loc).to_string())
496 .style(day_style)
497 .render(state.area_days[day.day0() as usize], buf);
498
499 if wd != Weekday::Sun && state.selection.is_selected(day + Days::new(1)) {
500 let mut gap_area = state.area_days[day.day0() as usize];
501 gap_area.x += 2;
502 gap_area.width = 1;
503 Span::from(" ").style(day_style).render(gap_area, buf);
504 }
505
506 x += 3;
507 day = day + Days::new(1);
508 } else {
509 x += 3;
510 }
511 }
512
513 w += 1;
514 x = state.inner.x;
515 y += 1;
516 }
517}
518
519fn calc_day_style<Selection: CalendarSelection>(
520 widget: &Month<'_, Selection>,
521 state: &mut MonthState<Selection>,
522 day: NaiveDate,
523 day_style: Style,
524 select_style: Style,
525) -> Style {
526 let day_style = if let Some(day_styles) = widget.day_styles {
527 if let Some(day_style) = day_styles.get(&day) {
528 *day_style
529 } else {
530 day_style
531 }
532 } else {
533 day_style
534 };
535
536 if (state.is_container_focused() || state.is_focused())
537 && state.selection.lead_selection() == Some(day)
538 {
539 day_style.patch(select_style.underlined())
540 } else if state.selection.is_selected(day) {
541 day_style.patch(select_style)
542 } else {
543 day_style
544 }
545}
546
547impl<Selection> HasFocus for MonthState<Selection> {
548 fn build(&self, builder: &mut FocusBuilder) {
549 builder.leaf_widget(self);
550 }
551
552 #[inline]
553 fn focus(&self) -> FocusFlag {
554 self.focus.clone()
555 }
556
557 #[inline]
558 fn area(&self) -> Rect {
559 self.area
560 }
561}
562
563impl<Selection> RelocatableState for MonthState<Selection> {
564 fn relocate(&mut self, shift: (i16, i16), clip: Rect) {
565 self.area.relocate(shift, clip);
566 self.inner.relocate(shift, clip);
567 self.area_cal.relocate(shift, clip);
568 self.area_weeknum.relocate(shift, clip);
569 self.area_days.relocate(shift, clip);
570 self.area_weeks.relocate(shift, clip);
571 }
572}
573
574impl<Selection> Clone for MonthState<Selection>
575where
576 Selection: Clone,
577{
578 fn clone(&self) -> Self {
579 Self {
580 area: self.area,
581 inner: self.inner,
582 area_cal: self.area_cal.clone(),
583 area_days: self.area_days.clone(),
584 area_weeknum: self.area_weeknum.clone(),
585 area_weeks: self.area_weeks.clone(),
586 start_date: self.start_date,
587 selection: self.selection.clone(),
588 container: self.container.clone(),
589 focus: FocusFlag::named(self.focus.name()),
590 mouse: Default::default(),
591 non_exhaustive: NonExhaustive,
592 }
593 }
594}
595
596impl<Selection> Default for MonthState<Selection>
597where
598 Selection: Default,
599{
600 fn default() -> Self {
601 Self {
602 area: Default::default(),
603 inner: Default::default(),
604 area_cal: Default::default(),
605 area_days: Default::default(),
606 area_weeknum: Default::default(),
607 area_weeks: Default::default(),
608 start_date: Default::default(),
609 selection: Default::default(),
610 container: Default::default(),
611 focus: Default::default(),
612 mouse: Default::default(),
613 non_exhaustive: NonExhaustive,
614 }
615 }
616}
617
618impl<Selection> MonthState<Selection> {
619 pub fn new() -> Self
620 where
621 Selection: Default,
622 {
623 Self::default()
624 }
625
626 pub fn named(name: &str) -> Self
627 where
628 Selection: Default,
629 {
630 Self {
631 focus: FocusFlag::named(name),
632 ..Self::default()
633 }
634 }
635
636 pub fn set_start_date(&mut self, date: NaiveDate) -> bool {
641 let old_value = self.start_date;
642 self.start_date = first_day_of_month(date);
643 old_value != self.start_date
644 }
645
646 pub fn start_date(&self) -> NaiveDate {
648 self.start_date
649 }
650
651 pub fn end_date(&self) -> NaiveDate {
653 last_day_of_month(self.start_date)
654 }
655
656 fn in_range(&self, date: NaiveDate) -> bool {
657 date >= self.start_date() && date <= self.end_date()
658 }
659
660 pub fn week_len(&self) -> usize {
662 Self::count_weeks(self.start_date)
663 }
664
665 pub fn count_weeks(day: NaiveDate) -> usize {
667 let mut day = day.with_day0(0).expect("date");
668 let month = day.month();
669
670 let mut weeks = 1;
671 for weekday in [
672 Weekday::Mon,
673 Weekday::Tue,
674 Weekday::Wed,
675 Weekday::Thu,
676 Weekday::Fri,
677 Weekday::Sat,
678 Weekday::Sun,
679 ] {
680 if day.weekday() == weekday {
682 day = day + Days::new(1);
683 }
684 }
685 while month == day.month() {
687 weeks += 1;
688 day = day + Days::new(7);
689 }
690
691 weeks
692 }
693
694 fn is_container_focused(&self) -> bool {
696 self.container
697 .as_ref()
698 .map(|v| v.is_focused())
699 .unwrap_or(false)
700 }
701}
702
703impl<Selection> MonthState<Selection>
704where
705 Selection: CalendarSelection,
706{
707 pub fn lead_selection(&self) -> Option<NaiveDate> {
709 self.selection.lead_selection()
710 }
711}
712
713impl MonthState<NoSelection> {}
714
715impl MonthState<SingleSelection> {
716 pub fn clear_selection(&mut self) {
718 self.selection.borrow_mut().clear();
719 }
720
721 pub fn select_day(&mut self, n: usize) -> CalOutcome {
723 if let Some(date) = self.start_date.with_day0(n as u32) {
724 if self.selection.borrow_mut().select(date) {
725 CalOutcome::Selected
726 } else {
727 CalOutcome::Continue
728 }
729 } else {
730 CalOutcome::Continue
731 }
732 }
733
734 pub fn select_last(&mut self) -> CalOutcome {
736 let date = self.end_date();
737 if self.selection.borrow_mut().select(date) {
738 CalOutcome::Selected
739 } else {
740 CalOutcome::Continue
741 }
742 }
743
744 pub fn select_date(&mut self, d: NaiveDate) -> bool {
748 let start = self.start_date;
749 if d.year() == start.year() && d.month() == start.month() {
750 self.selection.borrow_mut().select(d)
751 } else {
752 false
753 }
754 }
755
756 pub fn selected_date(&self) -> Option<NaiveDate> {
758 self.selection.lead_selection()
759 }
760
761 pub fn prev_day(&mut self, n: usize) -> CalOutcome {
763 let base_start = self.start_date();
764 let base_end = self.end_date();
765
766 let date = if let Some(date) = self.selection.lead_selection() {
767 if date >= base_start && date <= base_end {
768 date - Days::new(n as u64)
769 } else if date < base_start {
770 self.start_date()
771 } else {
772 self.end_date()
773 }
774 } else {
775 self.end_date()
776 };
777
778 if self.in_range(date) {
779 if self.selection.borrow_mut().select(date) {
780 CalOutcome::Selected
781 } else {
782 CalOutcome::Continue
783 }
784 } else {
785 CalOutcome::Continue
786 }
787 }
788
789 pub fn next_day(&mut self, n: usize) -> CalOutcome {
791 let base_start = self.start_date();
792 let base_end = self.end_date();
793
794 let date = if let Some(date) = self.selection.lead_selection() {
795 if date >= base_start && date <= base_end {
796 date + Days::new(n as u64)
797 } else if date < base_start {
798 self.start_date()
799 } else {
800 self.end_date()
801 }
802 } else {
803 self.start_date()
804 };
805
806 if self.in_range(date) {
807 if self.selection.borrow_mut().select(date) {
808 CalOutcome::Selected
809 } else {
810 CalOutcome::Continue
811 }
812 } else {
813 CalOutcome::Continue
814 }
815 }
816}
817
818impl MonthState<RangeSelection> {
819 pub fn clear_selection(&mut self) {
821 self.selection.borrow_mut().clear();
822 }
823
824 pub fn select_week(&mut self, n: usize, extend: bool) -> CalOutcome {
826 if n < self.week_len() {
827 let date = self.start_date() + Days::new(7 * n as u64);
828 if self.selection.borrow_mut().select_week(date, extend) {
829 CalOutcome::Selected
830 } else {
831 CalOutcome::Continue
832 }
833 } else {
834 CalOutcome::Continue
835 }
836 }
837
838 pub fn select_day(&mut self, n: usize, extend: bool) -> CalOutcome {
840 if let Some(date) = self.start_date.with_day0(n as u32) {
841 if self.selection.borrow_mut().select_day(date, extend) {
842 CalOutcome::Selected
843 } else {
844 CalOutcome::Continue
845 }
846 } else {
847 CalOutcome::Continue
848 }
849 }
850
851 pub fn select_last(&mut self, extend: bool) -> CalOutcome {
853 let date = self.end_date();
854 if self.selection.borrow_mut().select_day(date, extend) {
855 CalOutcome::Selected
856 } else {
857 CalOutcome::Continue
858 }
859 }
860
861 pub fn select_week_by_date(&mut self, date: NaiveDate, extend: bool) -> bool {
865 let base = self.start_date;
866
867 let start = date.week(Weekday::Mon).first_day();
868 let end = date.week(Weekday::Mon).last_day();
869
870 if (start.year() == base.year() && start.month() == base.month())
871 || (end.year() == base.year() && end.month() == base.month())
872 {
873 self.selection.borrow_mut().select_week(start, extend)
874 } else {
875 false
876 }
877 }
878
879 pub fn select_date(&mut self, d: NaiveDate, extend: bool) -> bool {
883 let base = self.start_date;
884 if d.year() == base.year() && d.month() == base.month() {
885 self.selection.borrow_mut().select_day(d, extend)
886 } else {
887 false
888 }
889 }
890
891 pub fn selected_date(&self) -> Option<NaiveDate> {
893 self.selection.lead_selection()
894 }
895
896 pub fn prev_day(&mut self, n: usize, extend: bool) -> CalOutcome {
898 let base_start = self.start_date();
899 let base_end = self.end_date();
900
901 let date = if let Some(date) = self.selection.lead_selection() {
902 if date >= base_start && date <= base_end {
903 date - Days::new(n as u64)
904 } else if date < base_start {
905 self.start_date()
906 } else {
907 self.end_date()
908 }
909 } else {
910 self.end_date()
911 };
912
913 if self.in_range(date) {
914 if self.selection.borrow_mut().select_day(date, extend) {
915 CalOutcome::Selected
916 } else {
917 CalOutcome::Continue
918 }
919 } else {
920 CalOutcome::Continue
921 }
922 }
923
924 pub fn next_day(&mut self, n: usize, extend: bool) -> CalOutcome {
926 let base_start = self.start_date();
927 let base_end = self.end_date();
928
929 let date = if let Some(date) = self.selection.lead_selection() {
930 if date >= base_start && date <= base_end {
931 date + Days::new(n as u64)
932 } else if date < base_start {
933 self.start_date()
934 } else {
935 self.end_date()
936 }
937 } else {
938 self.start_date()
939 };
940
941 if self.in_range(date) {
942 if self.selection.borrow_mut().select_day(date, extend) {
943 CalOutcome::Selected
944 } else {
945 CalOutcome::Continue
946 }
947 } else {
948 CalOutcome::Continue
949 }
950 }
951
952 pub fn prev_week(&mut self, n: usize, extend: bool) -> CalOutcome {
954 let base_start = self.start_date();
955 let base_end = self.end_date();
956
957 if let Some(date) = self.selection.lead_selection() {
958 let new_date = if date >= base_start && date <= base_end {
959 date - Days::new(7 * n as u64)
960 } else if date < base_start {
961 self.start_date()
962 } else {
963 self.end_date()
964 };
965 let new_date_end = new_date.week(Weekday::Mon).last_day();
966 if new_date_end >= base_start && new_date_end <= base_end {
967 if self.selection.borrow_mut().select_week(new_date, extend) {
968 CalOutcome::Selected
969 } else {
970 CalOutcome::Continue
971 }
972 } else {
973 CalOutcome::Continue
974 }
975 } else {
976 let new_date = self.end_date();
977 if self.selection.borrow_mut().select_week(new_date, extend) {
978 CalOutcome::Selected
979 } else {
980 CalOutcome::Continue
981 }
982 }
983 }
984
985 pub fn next_week(&mut self, n: usize, extend: bool) -> CalOutcome {
987 let start = self.start_date();
988 let end = self.end_date();
989
990 let new_date = if let Some(date) = self.selection.lead_selection() {
991 let date_end = date.week(Weekday::Mon).last_day();
992 if date_end >= start && date_end <= end {
993 date + Days::new(7 * n as u64)
994 } else if date_end < start {
995 self.start_date()
996 } else {
997 self.end_date()
998 }
999 } else {
1000 self.start_date()
1001 };
1002
1003 if new_date >= start && new_date <= end {
1004 if self.selection.borrow_mut().select_week(new_date, extend) {
1005 CalOutcome::Selected
1006 } else {
1007 CalOutcome::Continue
1008 }
1009 } else {
1010 CalOutcome::Continue
1011 }
1012 }
1013}