1+ use chrono:: NaiveDate ;
12use gpui:: {
23 anchored, deferred, div, prelude:: FluentBuilder as _, px, AppContext , ElementId , EventEmitter ,
34 FocusHandle , FocusableView , InteractiveElement as _, KeyBinding , Length , MouseButton ,
4- ParentElement as _, Render , SharedString , StatefulInteractiveElement as _, Styled as _ , View ,
5+ ParentElement as _, Render , SharedString , StatefulInteractiveElement as _, Styled , View ,
56 ViewContext , VisualContext as _,
67} ;
78use rust_i18n:: t;
89
910use crate :: {
10- dropdown:: Escape , h_flex, input:: ClearButton , theme:: ActiveTheme as _, Icon , IconName , Sizable ,
11- Size , StyleSized as _, StyledExt as _,
11+ button:: { Button , ButtonStyled as _} ,
12+ dropdown:: Escape ,
13+ h_flex,
14+ input:: ClearButton ,
15+ theme:: ActiveTheme ,
16+ v_flex, Icon , IconName , Sizable , Size , StyleSized as _, StyledExt as _,
1217} ;
1318
1419use super :: calendar:: { Calendar , CalendarEvent , Date } ;
@@ -23,6 +28,34 @@ pub enum DatePickerEvent {
2328 Change ( Date ) ,
2429}
2530
31+ #[ derive( Clone ) ]
32+ pub enum DateRangePresetValue {
33+ Single ( NaiveDate ) ,
34+ Range ( NaiveDate , NaiveDate ) ,
35+ }
36+
37+ #[ derive( Clone ) ]
38+ pub struct DateRangePreset {
39+ label : SharedString ,
40+ value : DateRangePresetValue ,
41+ }
42+
43+ impl DateRangePreset {
44+ /// Creates a new DateRangePreset with single date.
45+ pub fn single ( label : impl Into < SharedString > , single : NaiveDate ) -> Self {
46+ DateRangePreset {
47+ label : label. into ( ) ,
48+ value : DateRangePresetValue :: Single ( single) ,
49+ }
50+ }
51+ /// Creates a new DateRangePreset with a range of dates.
52+ pub fn range ( label : impl Into < SharedString > , start : NaiveDate , end : NaiveDate ) -> Self {
53+ DateRangePreset {
54+ label : label. into ( ) ,
55+ value : DateRangePresetValue :: Range ( start, end) ,
56+ }
57+ }
58+ }
2659pub struct DatePicker {
2760 id : ElementId ,
2861 focus_handle : FocusHandle ,
@@ -35,6 +68,7 @@ pub struct DatePicker {
3568 date_format : SharedString ,
3669 calendar : View < Calendar > ,
3770 number_of_months : usize ,
71+ presets : Option < Vec < DateRangePreset > > ,
3872}
3973
4074impl DatePicker {
@@ -82,6 +116,7 @@ impl DatePicker {
82116 cleanable : false ,
83117 number_of_months : 1 ,
84118 placeholder : None ,
119+ presets : None ,
85120 }
86121 }
87122
@@ -115,6 +150,12 @@ impl DatePicker {
115150 self
116151 }
117152
153+ /// Set preset ranges for the date picker.
154+ pub fn presets ( mut self , presets : Vec < DateRangePreset > ) -> Self {
155+ self . presets = Some ( presets) ;
156+ self
157+ }
158+
118159 /// Get the date of the date picker.
119160 pub fn date ( & self ) -> Date {
120161 self . date
@@ -158,6 +199,17 @@ impl DatePicker {
158199 self . open = !self . open ;
159200 cx. notify ( ) ;
160201 }
202+
203+ fn select_preset ( & mut self , preset : & DateRangePreset , cx : & mut ViewContext < Self > ) {
204+ match preset. value {
205+ DateRangePresetValue :: Single ( single) => {
206+ self . update_date ( Date :: Single ( Some ( single) ) , true , cx)
207+ }
208+ DateRangePresetValue :: Range ( start, end) => {
209+ self . update_date ( Date :: Range ( Some ( start) , Some ( end) ) , true , cx)
210+ }
211+ }
212+ }
161213}
162214
163215impl EventEmitter < DatePickerEvent > for DatePicker { }
@@ -190,8 +242,9 @@ impl Render for DatePicker {
190242 view. set_number_of_months ( self . number_of_months , cx) ;
191243 } ) ;
192244
193- let popover_width =
194- 285.0 * self . number_of_months as f32 + ( self . number_of_months - 1 ) as f32 * 16.0 ;
245+ let popover_width = self . presets . as_ref ( ) . map_or ( 0.0 , |_| 136.0 )
246+ + 285.0 * self . number_of_months as f32
247+ + ( self . number_of_months - 1 ) as f32 * 16.0 ;
195248
196249 div ( )
197250 . id ( self . id . clone ( ) )
@@ -266,7 +319,34 @@ impl Render for DatePicker {
266319 MouseButton :: Left ,
267320 cx. listener ( |view, _, cx| view. escape ( & Escape , cx) ) ,
268321 )
269- . child ( self . calendar . clone ( ) ) ,
322+ . child (
323+ h_flex ( )
324+ . gap_3 ( )
325+ . h_full ( )
326+ . items_start ( )
327+ . when_some ( self . presets . clone ( ) , |this, presets| {
328+ this. child (
329+ v_flex ( ) . my_1 ( ) . gap_2 ( ) . justify_end ( ) . children (
330+ presets. into_iter ( ) . enumerate ( ) . map (
331+ |( i, preset) | {
332+ Button :: new ( ( "preset" , i) )
333+ . small ( )
334+ . ghost ( )
335+ . label ( preset. label . clone ( ) )
336+ . on_click ( cx. listener (
337+ move |this, _, cx| {
338+ this. select_preset (
339+ & preset, cx,
340+ ) ;
341+ } ,
342+ ) )
343+ } ,
344+ ) ,
345+ ) ,
346+ )
347+ } )
348+ . child ( self . calendar . clone ( ) ) ,
349+ ) ,
270350 ) ,
271351 )
272352 . with_priority ( 2 ) ,
0 commit comments