Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
date.tcl
Go to the documentation of this file.
1 
2 namespace eval ::utils::date {}
3 
4 # ::utils::date::today:
5 # Returns todays date, in "yyyy.mm.dd" format.
6 # The optional parameter "year", "month" or "day" can be used to
7 # limit the returned value to just the year, month or day.
8 #
9 proc ::utils::date::today {{type all}} {
10  set timeNow [clock seconds]
11  set year [clock format $timeNow -format "%Y"]
12  set month [clock format $timeNow -format "%m"]
13  set day [clock format $timeNow -format "%d"]
14  switch -- $type {
15  "all" { return [format "%s.%s.%s" $year $month $day]}
16  "year" { return $year}
17  "month" { return $month}
18  "day" { return $day}
19  default { error "Unrecognised parameter: $type"}
20  }
21 }
22 
23 # ::utils::date::chooser
24 #
25 # Produce a date-selection dialog box.
26 # Originally based on code from Effective Tcl/Tk Programming by
27 # Mark Harrison, but with lots of changes and improvements.
28 #
29 proc ::utils::date::chooser {{date "now"}} {
30  set time [clock seconds]
31  if {$date != "now"} {
32  catch {set time [clock scan $date]}
33  }
34  set ::utils::date::_time $time
35  set ::utils::date::_selected [clock format $time -format "%Y-%m-%d"]
36 
37  set win .dateChooser
38  toplevel $win
39  canvas $win.cal -width 300 -height 220
41  pack [ttk::frame $win.b] -side bottom -fill x
42  ttk::button $win.b.ok -text "OK" -command "destroy $win"
43  ttk::button $win.b.cancel -text $::tr(Cancel) -command "
44  set ::utils::date::_selected {}
45  destroy $win"
46  pack $win.b.cancel $win.b.ok -side right -padx 5 -pady 5
47  pack $win.cal -side top -expand yes -fill both
48 
49  ttk::button $win.cal.prevY -image tb_start -command "::utils::date::_month $win -12"
50  ttk::button $win.cal.prev -image tb_prev -command "::utils::date::_month $win -1"
51  ttk::button $win.cal.next -image tb_next -command "::utils::date::_month $win +1"
52  ttk::button $win.cal.nextY -image tb_end -command "::utils::date::_month $win +12"
53  bind $win.cal <Configure> "::utils::date::_redraw $win"
54  bind $win.cal <Double-Button-1> "destroy $win"
55  bind $win <Escape> "$win.b.cancel invoke"
56  bind $win <Return> "$win.b.ok invoke"
57  bind $win <Prior> "$win.cal.prev invoke"
58  bind $win <Next> "$win.cal.next invoke"
59  bind $win <Shift-Prior> "$win.cal.prevY invoke"
60  bind $win <Shift-Next> "$win.cal.nextY invoke"
61  bind $win <Up> "::utils::date::_day $win -7"
62  bind $win <Down> "::utils::date::_day $win +7"
63  bind $win <Left> "::utils::date::_day $win -1"
64  bind $win <Right> "::utils::date::_day $win +1"
65 
66  wm minsize $win 250 200
67  wm title $win "Scid: Choose Date"
68  focus $win
69  grab $win
70  tkwait window $win
71  if {$::utils::date::_selected == ""} { return {}}
72  set time [clock scan $::utils::date::_selected]
73  return [list \
74  [clock format $time -format "%Y"] \
75  [clock format $time -format "%m"] \
76  [clock format $time -format "%d"]]
77 }
78 
79 proc ::utils::date::_day {win delta} {
80  set unit "day"
81  if {$delta < 0} {set unit "day ago"}
82  set time [clock scan "[expr abs($delta)] $unit" -base $::utils::date::_time]
83  set day [string trimleft [clock format $time -format "%d"] 0]
84  set month [string trimleft [clock format $time -format "%m"] 0]
85  set year [clock format $time -format "%Y"]
86  ::utils::date::_select $win "$year-$month-$day"
87 }
88 
89 proc ::utils::date::_month {win delta} {
90  set dir [expr {($delta > 0) ? 1 : -1}]
91  set day [string trimleft [clock format $::utils::date::_time -format "%d"] 0]
92  set month [string trimleft [clock format $::utils::date::_time -format "%m"] 0]
93  set year [clock format $::utils::date::_time -format "%Y"]
94 
95  for {set i 0} {$i < abs($delta)} {incr i} {
96  incr month $dir
97  if {$month < 1} {
98  set month 12
99  incr year -1
100  } elseif {$month > 12} {
101  set month 1
102  incr year 1
103  }
104  }
105  if {[catch {::date::_select $win "$year-$month-$day"}]} {
106  ::utils::date::_select $win "$year-$month-28"
107  }
108 }
109 
110 proc ::utils::date::_redraw {win} {
111  $win.cal delete all
112  set time $::utils::date::_time
113  set wmax [winfo width $win.cal]
114  set hmax [winfo height $win.cal]
115 
116  $win.cal create window 3 3 -anchor nw -window $win.cal.prevY
117  $win.cal create window 40 3 -anchor nw -window $win.cal.prev
118  $win.cal create window [expr {$wmax-43}] 3 -anchor ne -window $win.cal.next
119  $win.cal create window [expr {$wmax-3}] 3 -anchor ne -window $win.cal.nextY
120  set bottom [lindex [$win.cal bbox all] 3]
121 
122  set month [string trimleft [clock format $time -format "%m"] 0]
123  set year [clock format $time -format "%Y"]
124  $win.cal create text [expr {$wmax/2}] $bottom -anchor s -font font_Bold \
125  -text "[lindex $::tr(Months) [expr $month - 1]] $year"
126 
127  incr bottom 3
128  $win.cal create line 0 $bottom $wmax $bottom -width 2
129  incr bottom 25
130 
131  set current ""
132 
133  set layout [::utils::date::_layout $time]
134  set weeks [expr {[lindex $layout end]+1}]
135 
136  for {set day 0} {$day < 7} {incr day} {
137  set x0 [expr {$day*($wmax-7)/7+3}]
138  set x1 [expr {($day+1)*($wmax-7)/7+3}]
139  $win.cal create text [expr {($x1+$x0)/2}] $bottom -anchor s \
140  -text [lindex $::tr(Days) $day] -font font_Small
141  }
142  incr bottom 3
143 
144  foreach {day date dcol wrow} $layout {
145  set x0 [expr {$dcol*($wmax-7)/7+3}]
146  set y0 [expr {$wrow*($hmax-$bottom-4)/$weeks+$bottom}]
147  set x1 [expr {($dcol+1)*($wmax-7)/7+3}]
148  set y1 [expr {($wrow+1)*($hmax-$bottom-4)/$weeks+$bottom}]
149 
150  if {$date == $::utils::date::_selected} {set current $date}
151 
152  $win.cal create rectangle $x0 $y0 $x1 $y1 -outline black -fill white
153 
154  $win.cal create text [expr {$x0+4}] [expr {$y0+2}] -anchor nw -text "$day" \
155  -fill black -font font_Small -tags [list $date-text all-text]
156 
157  $win.cal create rectangle $x0 $y0 $x1 $y1 \
158  -outline "" -fill "" -tags [list $date-sensor all-sensor]
159 
160  $win.cal bind $date-sensor <ButtonPress-1> "::utils::date::_select $win $date"
161  }
162 
163  if {$current != ""} {
164  $win.cal itemconfigure $current-sensor -outline red -width 3
165  $win.cal raise $current-sensor
166  } elseif {$::utils::date::_selected == ""} {
167  set date [clock format $time -format "%Y-%m-%d"]
168  ::utils::date::_select $win $date
169  }
170 }
171 
172 proc ::utils::date::_layout {time} {
173  set month [string trimleft [clock format $time -format "%m"] 0]
174  set year [clock format $time -format "%Y"]
175 
176  foreach lastday {31 30 29 28} {
177  if {[catch {clock scan "$year-$month-$lastday"}] == 0} { break}
178  }
179  set seconds [clock scan "$year-$month-1"]
180  set firstday [clock format $seconds -format %w]
181  set weeks [expr {ceil(double($lastday+$firstday)/7)}]
182 
183  set rlist ""
184  for {set day 1} {$day <= $lastday} {incr day} {
185  set seconds [clock scan "$year-$month-$day"]
186  set date [clock format $seconds -format "%Y-%m-%d"]
187  set daycol [clock format $seconds -format %w]
188  set weekrow [expr {($firstday+$day-1)/7}]
189  lappend rlist $day $date $daycol $weekrow
190  }
191  return $rlist
192 }
193 
194 proc ::utils::date::_select {win date} {
195  set time [clock scan $date]
196  set date [clock format $time -format "%Y-%m-%d"]
197 
198  set currentMonth [clock format $::utils::date::_time -format "%m %Y"]
199  set selectedMonth [clock format $time -format "%m %Y"]
200  set ::utils::date::_time $time
201  set ::utils::date::_selected $date
202 
203  if {$currentMonth == $selectedMonth} {
204  $win.cal itemconfigure all-sensor -outline "" -width 1
205  $win.cal itemconfigure $date-sensor -outline red -width 3
206  $win.cal raise $date-sensor
207  } else {
209  }
210 }