My popup "Date Entry" widget with msgcat

Hi, this piece of code is a part of my software. Its a little "date picker" or "date entry" widget, Im not sure about a name :), so lets say its simple popup "Date Entry" I used to use great An i15d date chooser widget, but I wanted some extra stuff, so I came up with this one. In the future I want to add some extra stuff like in Date Picker - jQuery (unfortunately I cant do it right now, too busy looking for work :()

So what you can do with it:

  • you can use it (of course :))
  • you can configure personalized colors, font size and fonts type (to fit outlook of your own software)
  • you can use msgcat package to translate it (no need if you want it in English, Im posting Portuguese translation file, if you want to use it create folder lang copy it inside under name pt.msg)
  • you can set start of the week (Monday or Sunday, see code)

In the future, you should be able to see 3 months, 1 year calendar, select period of time. (If you can do it, please post a copy, so i can include in my software :))

How to use it:

  1. Create your entry widget
  2. Create your button
  3. Call ::DATE::my_popup_Cal name_of_your_entry_widget proc from -command (see code)

You can send a configuration dictionary to ::DATE::my_popup_Cal proc, possible keys are:

result_format - Any format groups recognized by the clock format command. (see code) week_start - Possible values are: Monday and Sunday (default is Monday)

That is all!

#!/bin/sh
# main.tcl \
exec tclsh "$0" ${1+"$@"}

package require Tk




namespace eval DATE {

#######################################################################################################
#  Set variables. Configure your stuff here
#######################################################################################################

set ::DATE::back_weekdays #00b70d                                        ;# Background color of day of the week

set ::DATE::back_days grey80                                                ;# Background color of days in the month
set ::DATE::back_pointer grey90                                                ;# Color of background highlighting

set ::DATE::fontcol_today blue                                                ;# Font color of today
set ::DATE::fontcol_year blue                                                ;# Font color of year
set ::DATE::fontcol_month blue                                                ;# Font color of month
set ::DATE::fontcol_days grey40                                                ;# Font color of normal days
set ::DATE::fontcol_sunday #ff0099                                        ;# Font color of sunday
set ::DATE::fontcol_saturday #ff1239                                        ;# Font color of saturday

set ::DATE::font_year {Helvetica 14}                                        ;# Font type and size of year frame
set ::DATE::font_month {Helvetica 10}                                        ;# Font type and size of month frame
set ::DATE::font_days {Helvetica 9}                                        ;# Font type and size of dyas frame


set ::DATE::sel_month [clock format [clock scan now] -format "%m"]
set ::DATE::sel_year [clock format [clock scan now] -format "%Y"]
set ::DATE::months [dict create 1 January 2 February 3 March 4 April 5 May 6 June 7 July 8 August 9 September 10 October 11 November 12 December]

set ::DATE::sundayWeek {"Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat"}
set ::DATE::mondayWeek {"Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"}
#######################################################################################################
#  Images
#######################################################################################################

set left [image create photo -data {
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlw
SFlzAAAK8AAACvABQqw0mAAAABh0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzT7MfTgAA
AuNJREFUSIntVU1IVFEYPd+kUjZpE1pg2a+LssBJStqYkk1lq1yXFo2TVpCQLazGhNKVtHBU
hIpQCgINrCnHWlXODEFhYxZl0QTVM8taSL6ZnHnv3q+F8xORQaEQ1IUD9913+c45953vXWJm
zOQwzGj1/wTTRpBrXr+SiFL/iIGZp8TateuyBgYed4TD2piiDA9UHana+Kv9P8PPF4HZ3d3X
jqqqOjo09ILt9lP8yOdjv/917+8SJPzoyH6y1qIow6eTk+dsam/vQFfXVXz+/Anp6Wk4YLOt
bnI0ly1auFCTQhiklBQ9BYDIMItw787doXMXzj+M1qNoo2VkLF7mdDrt2dlrrG6Ph9pa26AM
DyM1JQXBYBDFO4tRWVmBiVAILCMKEVcqJcNABJPJFO7v72/bts1SzcyCmBmHDx0222trnePq
eKajqRkejwdz5yYjKSkJYIDBICIYyABQTBuA+F+AGRBCR25uLmqO1+B27y1r2d6yi7OICBUH
K1v8fv+m/fv2Q1HeYZ7RCCKCkBJSSrCUEEJA0zTouh7B93MdQtMhJcPne4TMzKUoKCxMtNls
VxIAIBQKBxKTEiF0HVIQNE2LyEJMMTODJccdfPcu7okQDoWh6zqIyKCqKgx1dXWwnzhRv2L5
Cn/n1S7k5OTg44cPCAaC0IU+qTqiXAgBGYWUkEJGnicdhkIT2GqxYPuOHXC73d0ul4tjH3lJ
xpKlN1w367OyskpdPS6cbWzEyMgITPPnQw0EsKukBNXHqhEIBiNOCIjFEWBIEBHS0tL1J4OD
54uKtlQxsxaLqfJeeQugrKG+odNqKz+Tn59vbnE4cPnSJXwaHYXRaIRpwYI33deun47FlJmi
GQVNJtbr8b5saW2+H7sGpmg0Y0+P66SqBsa8Xi+X7t7DfX1ufvZ86Oa0dHIUBZsL1g0+edoZ
+Pr1y6tX/gfl1nLztBJEbeZtyFsFwPi7xZk53skzNf6O++DfJvgGRXumi1HnLrIAAAAASUVO
RK5CYII=}]

set right [image create photo -data {
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlw
SFlzAAAK8AAACvABQqw0mAAAABh0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzT7MfTgAA
AtVJREFUSIntVV1Ik1EYft5vc/7NTEy8qpt2kQ1XQZQZBc0bG9bd8ma7KGFWppGlkaYTvddI
pQzDLiqmaWQWVNPYBtq1ppGmzoSR+7rZ3E983ze/08WmqEliOAjqwMs5HJ7zPi/POc97iDGG
eA4urtn/E8SNgIh25h05qiGihE3BjLEtRX1d/UmPx/MpEAz63W73+7LLZSd+h98ygdvttg+P
fGAWy0XmcLpYMBQSnU5XM4CsjfC02gfWOqs+71jePsYYMTBGIAKBEQgKhWLJy3tVRqOxqqPj
we6urkdISUmBXn8KllILkpOSp2w2m7W8/IptjZyMMRBR4vDwyD2tVnue53nIsgyO40BEsQAA
AsCgVCrR2fkQdrsdqalqBAKLUKvTUFJyAUVFRZibm+s1m0w3R8dGZ1cIurt7SvUFBfdv19Zi
dHQMSoUC0azrXU4AAAXHgeM4MDAQESKRJQQWF6HT6VBVXYWMjIy5qxUVhX3P+yZJo9EoHE7X
y6HBQUNTYyOys7OxYfdY5iOAYkTLU3RJCIdDkKQI2trbkJmZ+USr3W9S+v1+gDGZMQZRFCFJ
Uux5/VL4yj4RQETrIARRFCGKIgRBgCpRlQoAHM/zS06H44XBYIBer0c4FIIoCFGwJEIUhZWD
0RAgShIkKYKIJCESieBHOIyFhW/IzdWhp/cZcnJyPHeaW5pWX3KCw+m6q8vNtXi9Xk6WZVC0
TFBMZxaTJzkpCS3NLRjo70eqWg2/z4ddWVmovH4DRWfPYGZm+rHZZLZOTIzPAoAyZjYJwKXq
quqn+cfzc+QlGWsVIMZxnOz9zqvMJvOtHTvS9vBeL9IFAcbiYlyrrIRKpfrY3tpaV1Nb0z8x
Mf7nTp6enhkaGHjFDIWn2aB9kAWCwdCbt++aAKRvi5MbrA0FX+fnv/h8ft/nyanXRuO5w9va
KmLOzzx04OBeANxm2DWtIh7j7/wP/i2Cn6ZGX0/txR+gAAAAAElFTkSuQmCC}]

set up [image create photo -data {
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlw
SFlzAAAK8AAACvABQqw0mAAAABh0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzT7MfTgAA
AwZJREFUSIm1lctPU1EQxr9zqyxEauICVIxaNYBKJDG2F0QBY6QYWbhxqUEXakw0SEx8/ANq
3PigxceCYIILE1/Ex6ZGZYGBKG7wiaUVbhEpj94r1lh7zucCfCwKtypOcjYnZ+aXmflmjiCJ
/2laug8rN1fmB4M9TX2GcW1Xza41aRNI2p6i1UWuaHQo9PRZJ9vannBoaLi/cGWhKx3ftAAv
ul5cD4XCXL+hnKWlGxgKh9nZ+bx5WgAnT5zcnpSSe/fuY1lZBcvKKnjwYC0T377x+LHj1f8E
ADDXNM3uGzdv0e3W6fVuoddbRbdb59279xiNRrsAOKeKMWWTA4HAsUQisbzB78fs2ZmQUkJK
hczMWaiv90FzOFa1tLTUTRVjUsDOHTuLy8srDpw7dx6jozFomgalFJRScDhmYHBwEBcaLqDS
6z1cvbW6aLI4ItUcCCFmBnt67keMyKba2kNwOp0/NAdAAAIAibGxz/D56uGc47yzoqBgG0mZ
VgZLFi3JzcnOKWlsbIRlmvhkWVBKTmQgoaSCZVmIjY7i0sVLyF2Qu3HxosULU8WakerStMzh
kZGR3pqamoL8vDyYloXWx60QQvx8U1VVhaysLHg8HsTM2MCXeDyWskaTdb+urq70XTB4Jx6P
h/s/fKDu0VlSvI7FeglLitdx4OMgx8Y+h4LBnntHjxyt+Os5OHvm7P7Xb97QvdZN3aPT49ap
e3S+fdvN06dO77HzT1mi383lciWUVFBSYVwPhICAUgpLly1N2PnbAqSUDoJQSkIDJ3QkQBJS
SttlaQsAIKgIKRV+SVoglbz/FgCSUDIJUAN/A3B8IqYHIJUaD04C4mcG0wNQ4/UG+KMHgKIC
YF8mW4AQApoQSHz9ioyMDABAMpmEpmnQNIdtBrYqaO/oeDVv/jys9bgRMQxEDAO6riM7Owcd
7e0vbVOw/TAA7eHDR5cNI0Kfz88GfwONSD8DgQd+TCzLf/4yAcxsbr66531v3+3w+96bTU1X
dgNwpOObcl1PZkIIsRxg9x/4fAdoLf31QoQzBAAAAABJRU5ErkJggg==}]

set down [image create photo -data {
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlw
SFlzAAAK8AAACvABQqw0mAAAABh0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzT7MfTgAA
AwVJREFUSImtlU9sDGEYxp93KhSlSe22pQcXbbcrldamuzTaIKk4Ian40zpUECSoSgjlwI0b
Lm7+xJ9KalsWFw66SKX+rNBK6Kqmu1RsTavtrJP5HochkeqaQb/ku0zmeX7zfu/zzick8TdL
ICCcazRHpiJpTU1XtyQSA6HEQOJmc/O17SIyyRGB5B83AITD4VPDIyNsbb3BYEsrv3wZ5oMH
D88AEFu93Qs7d+z0Jb9+ZWPjYfp8ZfT5ynjgwEGOGgYb9jYE7PS2ZVZWVhYNDQ7h6dNncLlc
AIBIJAJd11FeXl4EoONPeluAaJJmKhMiAtM0rWciUEoBDnpoC6AiQUApBaUUxCLACpJ9BO0B
JDkGIJr14YR9Xp1EjQBBKlApEIBYYAf2TioAoEgoU8FUJgQCIR0Pmy0gTdMUyF+OSCCaACQ0
TVN2etsURKPRyQRAKqsK04QyraPq6emZYltCqgHZvWt3oDsaDRnJ5LvPus7Fi8rpL/PTX+Zn
wL+Inz4laCSTva/fdF+vq9u8MJWPjPezE5Gpvb297X19sZL74TAMI4m2tnuWAFZfli5dhhkz
MrBs+XLMyZvTubJqRUX32+jwWK9UPZieNcuVd+L4CbQEg8jKykJGRgYAAX8QboZCGBwcRDwe
x8nTp71utzsHwG+AVBVIJPL8klKqZlNNDdLT06GJBsiP0bJyCsMwcPbCeWRmZoYWFBdXk/w2
1mvcJpPktq1bjxUWFg7V1NZC13Uo9bPBJmgq6LqO6uq1KC0tNfbVNxwZz/ynWcp95UrT/kRi
gAF/gAXz8lnsnc9i73x68gu4sKSUHz70s6Wl9eg//64BTIvF4s+C14LMdWfT6ymi11PEHJeb
ly5eZn//xy4AM//rPqjfU181OmqYG9atZ15OLvNyZ3PNqtUcGRll46HGVf994ZBEe/ujc51d
r5g9y8VcdzZfvOxkx+MnV51oHQHy5+XPjcXfv7916zbv3LnLvr5Yj6fQM3fCACSxYf3Gkjfd
0abOrldnK5ZUFDjVjTsHE7m+A5o9OsW1tXDMAAAAAElFTkSuQmCC}]

set calendar [image create photo -data {
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlw
SFlzAAAK8AAACvABQqw0mAAAABh0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzT7MfTgAA
BTZJREFUSIm1lmtsVEUUx39ze/fVbgsYodZ+UktLkGqgCNVtokLABkhAY0Sg2BqVxsRSTTAa
hdiEiihqYqyhfgMRQdJtPxijRdjWmPIQpFJtU6AkdlvdtoF2oeyju3dm/LAPl0d8fPAkk5s7
c+f/P+d/zpk7QmvN/2nG36wJIYTznwCS34j/RLDj7Xcqh4d//z4YvHLq5ImTu4UQ024BPO3Y
sePNl8fHTw0O+jsbGxsrb8mgtb5uAM4//gj4fb5O/cEHH+qxsTHd1tq25cbvvF7vq4HAiH7/
/Q/1kaM+PTQ07AecN+FlvjRuf3v5UZ/vE0tKWV39rC4unqN9HR06GAz2dHd37+jp6dl19uzZ
XadPn94xMTHR892RI7q4eI6uqXlWT8Vi8qjP19z0cdMaICuFaSbDNTo6Oj+q21z30oULFxgc
HMRmM3E6nUxOXmNoaKg0blmlccsCDUophoeHuTYZwuVyYZo2/P4hw+V01T69bl3tosWLDwkh
arTWEROgqemT1fPnz3+poaGBb775lqqqKsoWLmRiIojdbqe+/hXCoRDCMJKyKrKzc9jy6haK
ioooK1vAwYMHObD/CxYtXsTOnTufamnx/gA0ZTU0NDB9+vRXzp07V7Z7dzP5+bPw+4coKSnh
/vvvw+froK+vj7xpeTidDkwzi6mpGMFgkMuXL7NkyRKktGhvP0xOTjYXL17kzsJCKjweysoW
HDAB7Hab+8rVq5imidYQi02xZ88e4vE4breb119/Da+3lbHRUZTWrFq1Eo/Hw+joKF5vK/39
/cyceTtCGJimjUg4jBDCNjAwYDMAlNJaAEpJlJIJGZRCANu2bWXDhvXcffddjI+P8+bWN9i2
bSsOh4OHH3mYlpZDeDwPEQlHUDKxXyDQyZI0MstVSYWUkqnoFHPvncu+z/exfPkyACavTlJe
Xs7KFStobv6UNavX8PjqxwkEAsybN49oNIpSKkGi1c2NliCQhEMhikuK2bs3IdGXXx4CIBqN
UlFRgVKKw+2HWbt2LeUPllNVtZF9ez/D7XYnFJAKrf46fsxMAillouQG/dRuqqWzo5ON1c8k
PDEM7iwsIBaLs71xOwUFBdx22wwGBi6yuW4zoyMj2B12ZCoCcYsIpLTQWnPt2iTHurpQSuFw
ONLrhmHgdDr49ZdfeLC8nOrqGoqK7qH+5XrC4TBSyjQGOoNAk2gemdRQK43D4USTyAtAPB7j
SvAKAPv370cgON7VRW9vH6WlpbiyXUjLQkoFWqfwb85BeiiJsiQ6mTCtNGfOnAFg9uzZjIwE
cLlczJo1i0uXLhEOhRJOSpk6gzJzoFFKYVlWIkQSElpWHCMrCwB3rhtvSwubajfx7q73KCws
5CGPh5kzb6fhrbeIxWLY7XaUtFBa35gDIWTS88ynabPR/dMZjh8/wYXz54lGImxcv4E2bytr
nngCgBeee56vv/qKnOzs9D6tVDoHZlKemM1mIxqJoPLyUsc2ToeDUz+eZO2TT+JwOMh1uwkE
AtTX1eF0OonHYgghcOfmYlkWQohEP2iNMAyRn59vmQCnfzzV5anw1BSXlNDX24vdbifTNJpo
JHLd3GQSPNUjAJZlkX9HAUuXLuVcf/+JkZERJbTWCCFyurt/bp0+Y8byw+3thEMhDCOtHul4
U6WRMZVZhXa7jUeXLCXLMLofW7as8jf/4JhIySGEyG1ta3tx4cIHVhhZRl6ifG781eo0euZd
IemkobWO9PX2Hq2sfKxJaz0GkCZImUjEfb1G/94srbW8Du//vrb8Cfk3BWpw3nPLAAAAAElF
TkSuQmCC}]

#######################################################################################################
#  Procedures
#######################################################################################################


proc ::DATE::check_config {{userDict 0}} {
        set ::DATE::default_config_values [dict create result_format "%d-%m-%Y" calendars "1" start_date [clock scan now] week_start Monday]
        if {$userDict == 0} {
                foreach j [dict keys $::DATE::default_config_values] i [dict values $::DATE::default_config_values] {
                        set ::DATE::$j $i
                }
        } else {
                foreach j [dict keys $::DATE::default_config_values] {
                        if {[dict exists $userDict $j] == 1} {
                                set ::DATE::$j [dict get $userDict $j]
                        } else {
                                set ::DATE::$j [dict get $::DATE::default_config_values $j]
                        }
                }
        }
}

proc ::DATE::close {} {
        destroy $::DATE::w
}

proc ::DATE::get_monthname {months num} {
        return [dict get $months [string trimleft $num 0]]
}

proc ::DATE::plus {} {
        set ::DATE::sel_month "[expr $::DATE::sel_month + 1]"
        if {$::DATE::sel_month == 13} {
                set ::DATE::sel_month 1
                set ::DATE::sel_year [expr $::DATE::sel_year + 1]
        }
        ::DATE::update_month
        ::DATE::update_year
        ::DATE::update_days
}

proc ::DATE::minus {} {
        set ::DATE::sel_month "[expr $::DATE::sel_month - 1]"
        if {$::DATE::sel_month == 0} {
                set ::DATE::sel_month 12
                set ::DATE::sel_year [expr $::DATE::sel_year - 1]
        }
        ::DATE::update_month
        ::DATE::update_year
        ::DATE::update_days
}

proc ::DATE::plus_year {} {
        set ::DATE::sel_year [expr $::DATE::sel_year + 1]
        ::DATE::update_year
        ::DATE::update_days
}

proc ::DATE::minus_year {} {
        set ::DATE::sel_year [expr $::DATE::sel_year - 1]
        ::DATE::update_year
        ::DATE::update_days
}
 
proc ::DATE::update_month {} {
        $::DATE::a configure -text "[::msgcat::mc "[get_monthname $::DATE::months $::DATE::sel_month]"]"
}

proc ::DATE::update_year {} {
        global b
        $::DATE::b configure -text "$::DATE::sel_year"
}

proc ::DATE::days_in_month {month year} {
        if {$month==12} {set month 1; incr year}
        return [clock format [clock scan "[incr month]/1/$year  1 day ago"] -format %d]
}

proc ::DATE::day_weekday {day month year} {
        return [clock format [clock scan $month/$day/$year] -format %u]
}

proc ::DATE::today_color {day month year} {
        if {[string trimleft [clock format [clock scan now] -format "%d"] 0] == $day} {
                return $::DATE::fontcol_today
        } elseif {[clock format [clock scan $month/$day/$year] -format "%u"] == 7} {
                return $::DATE::fontcol_sunday
        } elseif {[clock format [clock scan $month/$day/$year] -format "%u"] == 6} {
                return $::DATE::fontcol_saturday
        } else {
                return $::DATE::fontcol_days
        }
}

proc ::DATE::hightlight {widget} {
        bind $widget <Any-Enter> {
                %W configure -background $::DATE::back_pointer
                update
        }
                
        bind $widget <Any-Leave> {
                %W configure -background $::DATE::back_days
                update
        } 
}

proc ::DATE::update_days {} {
        destroy $::DATE::days
        set days [frame $::DATE::main.days -background $::DATE::back_days]
        grid $::DATE::days -column 0 -row 2
        if {$::DATE::week_start == "Sunday"} {
                set startcol [expr [day_weekday 1 $::DATE::sel_month $::DATE::sel_year] + 1]
                if {$startcol == 8} {set startcol 1}
        } else {
                set startcol [day_weekday 1 $::DATE::sel_month $::DATE::sel_year]
        }
        set startrow 1
                for {set x 1} {$x <= [days_in_month $::DATE::sel_month $::DATE::sel_year]} {incr x} {
                        set a [label $::DATE::days.day$x -text "$x" -width 1 -justify center -anchor center -width 4 -font $::DATE::font_days -foreground [today_color $x $::DATE::sel_month $::DATE::sel_year] -textvariable "$x $::DATE::sel_month $::DATE::sel_year" -background $::DATE::back_days ]
                        grid $::DATE::days.day$x -column $startcol -row $startrow
                        ::DATE::hightlight $::DATE::days.day$x
                        incr startcol
                        if {$startcol == 8} {set startcol 1; incr startrow}
                }
}

proc ::DATE::format_result {sent} {
        set tmp [clock scan $sent -format {%d %m %Y}]
        set result [clock format $tmp -format $::DATE::result_format]
        ::DATE::update_entry $result
}

proc update_entry {result} {
        global userEntry
        $userEntry delete 0 end
        $userEntry insert 0 $result
}

proc ::DATE::my_popup_Cal {userEntry {userDict 0}} {
        set ::userEntry $userEntry
        ::DATE::check_config $userDict
        if {[winfo exists .d] == "1"} {::DATE::close}
        set ::DATE::w [toplevel .d]
        wm overrideredirect $::DATE::w 1
        lassign [winfo pointerxy .] x y
        wm geometry $::DATE::w "+${x}+${y}"

        grid [set ::DATE::main [frame $::DATE::w.f -borderwidth 1 -relief solid -takefocus 1]] -column 0 -row 0

        set ::DATE::month [frame $::DATE::main.month]
        set ::DATE::weekday [frame $::DATE::main.weekday]
        set ::DATE::days [frame $::DATE::main.days -background $::DATE::back_days]
        set ::DATE::year [frame $::DATE::main.year]

        grid $::DATE::month -column 0 -row 0
        grid $::DATE::weekday -column 0 -row 1
        grid $::DATE::days -column 0 -row 2
        grid $::DATE::year -column 0 -row 3


        button $::DATE::month.p -text "<" -relief flat -width 1 -command "::DATE::minus" -image $::DATE::left -width 18
        button $::DATE::month.n -text ">" -relief flat -width 1 -command "::DATE::plus" -image $::DATE::right -width 18
        set ::DATE::a [ttk::label $::DATE::month.month_name -text "[::msgcat::mc "[get_monthname $::DATE::months $::DATE::sel_month]"]" -width 20 -justify center -anchor center -font $::DATE::font_month -foreground $::DATE::fontcol_month]

        if {$::DATE::week_start == "Sunday"} {
                set weekday_list $::DATE::sundayWeek
        } else {
                set weekday_list $::DATE::mondayWeek

        }

        foreach j $weekday_list i {1 2 3 4 5 6 7} {
                ttk::label $::DATE::weekday.wday$i -text "[::msgcat::mc "$j"]" -width 4 -justify center -anchor center -background $::DATE::back_weekdays -font $::DATE::font_days
                grid $::DATE::weekday.wday$i -column $i -row 1
        }

        button $::DATE::year.p -text "<<" -relief flat -width 1 -command "::DATE::minus_year" -image $::DATE::down -width 14
        button $::DATE::year.n -text ">>" -relief flat -width 1 -command "::DATE::plus_year" -image  $::DATE::up -width 14
        set ::DATE::b [ttk::label $::DATE::year.year_name -text "$::DATE::sel_year" -width 10 -justify center -anchor center -font $::DATE::font_year -foreground $::DATE::fontcol_year]



        grid $::DATE::month.p -column 0 -row 0
        grid $::DATE::month.month_name -column 1 -row 0 -columnspan 5
        grid $::DATE::month.n -column 6 -row 0

        grid $::DATE::year.p -column 0 -row 5
        grid $::DATE::year.year_name -column 1 -row 5 -columnspan 5
        grid $::DATE::year.n -column 6 -row 5

        update_days

        bind $::DATE::w <ButtonRelease> {
                grab release [grab current]
                set what [winfo containing %X %Y]
                winfo class [winfo containing %X %Y]
                if {[winfo class [winfo containing %X %Y]] == "Label"} {
                        ::DATE::format_result [$what cget -textvariable]
                        ::DATE::close
                }
        }

}

}


#######################################################################################################
#  Example 
#######################################################################################################




#######################################################################################################
#  Load Translations
#######################################################################################################
# msgcat::mclocale pt
# msgcat::mcload [file join [file dirname [info script]] lang]




pack [frame .m]
pack [ttk::label .m.l -text "Chose a day:"] -side left
pack [ttk::entry .m.datae] -padx 10 -side left
pack [ttk::button .m.button -image $::DATE::calendar -command {::DATE::my_popup_Cal .m.datae}] -padx 5 -side right


pack [frame .n]
pack [ttk::label .n.l -text "Chose a day:"] -side left
pack [ttk::entry .n.datae] -padx 10 -side left
set config [dict create result_format "%Y/%m/%d, %A" week_start Sunday]
pack [ttk::button .n.button -image $::DATE::calendar -command {::DATE::my_popup_Cal .n.datae $config}] -padx 5 -side right



Siqsuruq - 2011-10-09 16:57:47

I forgot screenshots :) https://sites.google.com/a/msysc.org/intranet/1.png https://sites.google.com/a/msysc.org/intranet/2.png


Jeff Smith 2021-02-08 : Below is an online demo using CloudTk. This demo runs "My popup "Date Entry" widget with msgcat" in an Alpine Linux Docker Container. It is a 27.4MB image which is made up of Alpine Linux + tclkit + My-popup-Date-Entry-widget-with-msgcat.kit + libx11 + libxft + fontconfig + ttf-linux-libertine. It is run under a user account in the Container. The Container is restrictive with permissions for "Other" removed for "execute" and "read" for certain directories.


  use clock for local month and weekday names

HaO 2013-09-27: Even if this page is called "Using msgcat", one may use the clock package to get localized day and month names:

Abreviated weekday name:

clock format [clock scan $dayCur -format %w] -format "%a" -locale [msgcat::mclocale]

Month name:

clock format [clock scan ${monthCur}-1 -format %m-%d] -format "%B" -locale [msgcat::mclocale]

Great widget!

  Addition to [tG²]

SeS 29th Oct 2015

Hi, I have included this widget as a plugin wrapper to tG², user is able to pick and place this widget with the Layout Editor interface, set the label & entry as visible or not, set the font and some more parameters, easy as 1, 2, 3. Custom defined "plugin wrapper" is a new concept & implementation for tG², not yet released.

Thank you, and obviously, referred in the plugin wrapper to this wiki page and author.

  Found bug in proc ::DATE::get_monthname

SeS 9th Feb 2016

The following I have observed using a wish console created with tcl/tk v8.4.19 with package dict v8.5.3.1. When I activate the date picker with the icon, I get the following error:

  key "02" not known in dictionary
  key "02" not known in dictionary
      while executing
  "dict get $months $num"
      (procedure "get_monthname" line 3)
      invoked from within
  "get_monthname $::DATE::months $::DATE::sel_month"
      (procedure "::DATE::my_popup_Cal" line 26)

It seems, the '0' preceding the '2' (reference to current month, February) is the cause of the error. The way I fixed this is as following:

  proc ::DATE::get_monthname {months num} {
    return [dict get $months [string trimleft $num 0]]
  }

Happy with the solution, didn't bother to check if error is maybe depending on the specific combination of tcl/tk & dict versions that I use...