Keith Vetter 2008-10-08 : Here's a new time picker mega-widget based on an experimental one at [L1 ]. It works with and without Tile (the demo lets you switch between the two).
Couple of bugs I haven't worked out.
##+########################################################################## # # TimePicker.tcl -- another time picking tool # by Keith Vetter Oct 08, 2008 # # Based on widget at # http://haineault.com/media/examples/jquery-utils/demo/ui-timepickr.html # # Bugs: # o better highlighting under Tile (just pressed state isn't enough) # o when time entry widgets moves or gets raised or lowered, the popup windows # should follow # o only one instance allowed at a time (global TC array) # package require Tk package require Ttk catch {namespace delete timePicker} namespace eval timePicker { variable TC array set TC { popup,1 ?.__timepicker1 popup,2 ?.__timepicker2 popup,3 ?.__timepicker3 master ? UseTile 1 theTime "1:00 am" hour 0 minute 0 ampm 0 selected,hour 0 selected,minute 0 selected,ampm 0 selected,color \#b2b4bf } } ##+########################################################################## # # timePicker::timePicker -- Creates a new instance of our timepicker widget # proc timePicker::timePicker {w {UseTile 0}} { variable TC set TC(master) $w set TC(UseTile) $UseTile set TC(popup,1) $w.__timepicker1 set TC(popup,2) $w.__timepicker2 set TC(popup,3) $w.__timepicker3 entry $w -width 8 -textvariable timePicker::TC(theTime) bind $w <Enter> [list timePicker::ButtonEnter theTime -] return w } ##+########################################################################## # # timePicker::ButtonEnter -- Reacts to entering a button # proc timePicker::ButtonEnter {who which} { variable TC if {$who eq "theTime"} { if {! [winfo exists $TC(popup,1)] || ! [winfo ismapped $TC(popup,1)]} { timePicker::Init update idletasks timePicker::ShowHours } return } set TC($who) $which timePicker::DoHighlight $who $TC(selected,$who) $which set TC(selected,$who) $which set hour [expr {$TC(selected,hour) + 1 + $TC(selected,ampm)*12}] set minute [expr {$TC(selected,minute) * 15}] set seconds [expr {$hour * 3600 + $minute * 60}] set TC(theTime) [clock format $seconds -gmt 1 -format "%I:%M %P"] if {$who eq "hour"} { timePicker::ShowMinutes if {[winfo ismapped $TC(popup,3)]} { update idletasks timePicker::ShowAMPM } } if {$who eq "minute"} timePicker::ShowAMPM } proc timePicker::Init {} { variable TC timePicker::CreatePopup # Figure current time and hightlight those buttons foreach {hour minute ampm} {1 0 am} break set n [catch { set seconds [clock scan $TC(theTime) -format "%I:%M %P"] set ttime [clock format $seconds -format "%I %M %P"] scan $ttime "%d %d %s" hour minute ampm }] set minute [expr {int($minute/15)}] set TC(selected,hour) [expr {$hour-1}] set TC(selected,minute) $minute set TC(selected,ampm) [expr {$ampm eq "am" ? 0 : 1}] timePicker::DoHighlight hour 0 $TC(selected,hour) timePicker::DoHighlight minute 0 $TC(selected,minute) timePicker::DoHighlight ampm 0 $TC(selected,ampm) } proc timePicker::Done {} { variable TC wm withdraw $TC(popup,1) wm withdraw $TC(popup,2) wm withdraw $TC(popup,3) } ##+########################################################################## # # timePicker::PlacePopup -- Places a slave window just below master # proc timePicker::PlacePopup {master slave} { variable TC set x [winfo rootx $master] set y [winfo rooty $master] set y [expr {$y + [winfo height $master]}] wm geom $slave +$x+$y } proc timePicker::DoHighlight {who old new} { variable TC set id [expr {$who eq "hour" ? 1 : $who eq "minute" ? 2 : 3}] set w1 $TC(popup,$id).${who}_$old set w2 $TC(popup,$id).${who}_$new if {$TC(UseTile)} { $w1 state !pressed $w2 state pressed } else { $w1 config -bg [lindex [$w1 config -background] 3] $w2 config -bg $TC(selected,color) } } proc timePicker::ShowHours {} { variable TC timePicker::PlacePopup $TC(master) $TC(popup,1) if {[winfo ismapped $TC(popup,1)]} return wm deiconify $TC(popup,1) } proc timePicker::ShowMinutes {} { variable TC set master $TC(popup,1).hour_$TC(selected,hour) timePicker::PlacePopup $master $TC(popup,2) if {[winfo ismapped $TC(popup,2)]} return wm deiconify $TC(popup,2) } proc timePicker::ShowAMPM {} { variable TC timePicker::PlacePopup $TC(popup,2) $TC(popup,3) if {[winfo ismapped $TC(popup,3)]} return wm deiconify $TC(popup,3) } proc timePicker::CreatePopup {} { variable TC if {[winfo exists $TC(popup,1)]} { timePicker::Done return } foreach id {1 2 3} { toplevel $TC(popup,$id) wm withdraw $TC(popup,$id) wm overrideredirect $TC(popup,$id) 1 wm transient $TC(popup,$id) [winfo toplevel $TC(master)] catch { wm attributes $TC(popup,$id) -topmost 1 } } set button [expr {$TC(UseTile) ? "::ttk::button" : "button"}] set bw 3 for {set hour 0} {$hour < 12} {incr hour} { set h [format %02d [expr {$hour+1}]] set w $TC(popup,1).hour_$hour $button $w -text $h -width $bw -command timePicker::Done bind $w <Enter> [list timePicker::ButtonEnter hour $hour] grid $w -row 1 -column $hour } for {set minute 0} {$minute < 4} {incr minute} { set m [format %02d [expr {$minute * 15}]] set w $TC(popup,2).minute_$minute $button $w -text $m -width $bw -command timePicker::Done bind $w <Enter> [list timePicker::ButtonEnter minute $minute] grid $w -row 2 -column $minute } set w1 $TC(popup,3).ampm_0 set w2 $TC(popup,3).ampm_1 $button $w1 -text "am" -width $bw -command timePicker::Done bind $w1 <Enter> [list timePicker::ButtonEnter ampm 0] $button $w2 -text "pm" -width $bw -command timePicker::Done bind $w2 <Enter> [list timePicker::ButtonEnter ampm 1] grid $w1 $w2 -row 0 } ##+########################################################################## # # Demo Code # set UseTile 0 proc ReDemo {} { destroy .time timePicker::timePicker .time $::UseTile grid .time -row 2 } timePicker::timePicker .time $UseTile label .title -text "Time Picker Demo" -font {Times 48 bold} label .l1 -text "Here's a new timePicker widget\nmouse into and play" \ -font {Times 18 bold} frame .buttons checkbutton .tile -text "Tile" -variable ::UseTile -command ReDemo ::ttk::button .done -text Close -command exit grid .title -row 0 grid .l1 -row 1 grid .buttons -row 3 -pady {.75i 30} -sticky ew pack .tile .done -in .buttons -side left -expand 1 ReDemo return