summaryrefslogtreecommitdiff
path: root/itcl/iwidgets3.0.0/generic/spindate.itk
diff options
context:
space:
mode:
Diffstat (limited to 'itcl/iwidgets3.0.0/generic/spindate.itk')
-rw-r--r--itcl/iwidgets3.0.0/generic/spindate.itk700
1 files changed, 700 insertions, 0 deletions
diff --git a/itcl/iwidgets3.0.0/generic/spindate.itk b/itcl/iwidgets3.0.0/generic/spindate.itk
new file mode 100644
index 00000000000..0d9cda138ac
--- /dev/null
+++ b/itcl/iwidgets3.0.0/generic/spindate.itk
@@ -0,0 +1,700 @@
+# Spindate
+# ----------------------------------------------------------------------
+# Implements a Date spinner widget. A date spinner contains three
+# Spinner widgets: one Spinner for months, one SpinInt for days,
+# and one SpinInt for years. Months can be specified as abbreviated
+# strings, integers or a user-defined list. Options exist to manage to
+# behavior, appearance, and format of each component spinner.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Sue Yockey EMAIL: yockey@actc.com
+# Mark L. Ulferts mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 DSC Technologies Corporation
+# ======================================================================
+# Permission to use, copy, modify, distribute and license this software
+# and its documentation for any purpose, and without fee or written
+# agreement with DSC, is hereby granted, provided that the above copyright
+# notice appears in all copies and that both the copyright notice and
+# warranty disclaimer below appear in supporting documentation, and that
+# the names of DSC Technologies Corporation or DSC Communications
+# Corporation not be used in advertising or publicity pertaining to the
+# software without specific, written prior permission.
+#
+# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
+# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
+# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
+# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
+# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+# SOFTWARE.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Spindate.monthLabel "Month" widgetDefault
+option add *Spindate.dayLabel "Day" widgetDefault
+option add *Spindate.yearLabel "Year" widgetDefault
+option add *Spindate.monthWidth 4 widgetDefault
+option add *Spindate.dayWidth 4 widgetDefault
+option add *Spindate.yearWidth 4 widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Spindate {
+ keep -background -cursor -foreground -labelfont -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# SPINDATE
+# ------------------------------------------------------------------
+class iwidgets::Spindate {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -labelpos labelPos Position w
+ itk_option define -orient orient Orient vertical
+ itk_option define -monthon monthOn MonthOn true
+ itk_option define -dayon dayOn DayOn true
+ itk_option define -yearon yearOn YearOn true
+ itk_option define -datemargin dateMargin Margin 1
+ itk_option define -yeardigits yearDigits YearDigits 4
+ itk_option define -monthformat monthFormat MonthFormat integer
+
+ public {
+ method get {{format "-string"}}
+ method show {{date now}}
+ }
+
+ protected {
+ method _packDate {{when later}}
+ variable _repack {} ;# Reconfiguration flag.
+ }
+
+ private {
+ method _lastDay {month year}
+ method _spinMonth {direction}
+ method _spinDay {direction}
+
+ variable _monthFormatStr "%m"
+ variable _yearFormatStr "%Y"
+ variable _interior
+ }
+}
+
+#
+# Provide a lowercased access method for the Spindate class.
+#
+proc ::iwidgets::spindate {pathName args} {
+ uplevel ::iwidgets::Spindate $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+body iwidgets::Spindate::constructor {args} {
+ set _interior $itk_interior
+
+ set clicks [clock seconds]
+
+ #
+ # Create Month Spinner
+ #
+ itk_component add month {
+ iwidgets::Spinner $itk_interior.month -fixed 2 -justify right \
+ -decrement [code $this _spinMonth -1] \
+ -increment [code $this _spinMonth 1]
+ } {
+ keep -background -cursor -arroworient -foreground \
+ -labelfont -labelmargin -relief -textbackground \
+ -textfont -repeatdelay -repeatinterval
+
+ rename -labeltext -monthlabel monthLabel Text
+ rename -width -monthwidth monthWidth Width
+ }
+
+ #
+ # Take off the default bindings for selction and motion.
+ #
+ bind [$itk_component(month) component entry] <1> {break}
+ bind [$itk_component(month) component entry] <Button1-Motion> {break}
+
+ #
+ # Create Day Spinner
+ #
+ itk_component add day {
+ iwidgets::Spinint $itk_interior.day -fixed 2 -justify right \
+ -decrement [code $this _spinDay -1] \
+ -increment [code $this _spinDay 1]
+ } {
+ keep -background -cursor -arroworient -foreground \
+ -labelfont -labelmargin -relief -textbackground \
+ -textfont -repeatdelay -repeatinterval
+
+ rename -labeltext -daylabel dayLabel Text
+ rename -width -daywidth dayWidth Width
+ }
+
+ #
+ # Take off the default bindings for selction and motion.
+ #
+ bind [$itk_component(day) component entry] <1> {break}
+ bind [$itk_component(day) component entry] <Button1-Motion> {break}
+
+ #
+ # Create Year Spinner
+ #
+ itk_component add year {
+ iwidgets::Spinint $itk_interior.year -fixed 2 -justify right \
+ -range {1900 3000}
+ } {
+ keep -background -cursor -arroworient -foreground \
+ -labelfont -labelmargin -relief -textbackground \
+ -textfont -repeatdelay -repeatinterval
+
+ rename -labeltext -yearlabel yearLabel Text
+ rename -width -yearwidth yearWidth Width
+ }
+
+ #
+ # Take off the default bindings for selction and motion.
+ #
+ bind [$itk_component(year) component entry] <1> {break}
+ bind [$itk_component(year) component entry] <Button1-Motion> {break}
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+
+ #
+ # Show the current date.
+ #
+ show now
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+body iwidgets::Spindate::destructor {} {
+ if {$_repack != ""} {after cancel $_repack}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -labelpos
+#
+# Specifies the location of all 3 spinners' labels.
+# ------------------------------------------------------------------
+configbody iwidgets::Spindate::labelpos {
+ switch $itk_option(-labelpos) {
+ n {
+ $itk_component(month) configure -labelpos n
+ $itk_component(day) configure -labelpos n
+ $itk_component(year) configure -labelpos n
+
+ #
+ # Un-align labels
+ #
+ $itk_component(month) configure -labelmargin 1
+ $itk_component(day) configure -labelmargin 1
+ $itk_component(year) configure -labelmargin 1
+ }
+
+ s {
+ $itk_component(month) configure -labelpos s
+ $itk_component(day) configure -labelpos s
+ $itk_component(year) configure -labelpos s
+
+ #
+ # Un-align labels
+ #
+ $itk_component(month) configure -labelmargin 1
+ $itk_component(day) configure -labelmargin 1
+ $itk_component(year) configure -labelmargin 1
+ }
+
+ w {
+ $itk_component(month) configure -labelpos w
+ $itk_component(day) configure -labelpos w
+ $itk_component(year) configure -labelpos w
+ }
+
+ e {
+ $itk_component(month) configure -labelpos e
+ $itk_component(day) configure -labelpos e
+ $itk_component(year) configure -labelpos e
+
+ #
+ # Un-align labels
+ #
+ $itk_component(month) configure -labelmargin 1
+ $itk_component(day) configure -labelmargin 1
+ $itk_component(year) configure -labelmargin 1
+ }
+
+ default {
+ error "bad labelpos option \"$itk_option(-labelpos)\",\
+ should be n, s, w or e"
+ }
+ }
+
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -orient
+#
+# Specifies the orientation of the 3 spinners for Month, Day
+# and year.
+# ------------------------------------------------------------------
+configbody iwidgets::Spindate::orient {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -monthon
+#
+# Specifies whether or not to display the month spinner.
+# ------------------------------------------------------------------
+configbody iwidgets::Spindate::monthon {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -dayon
+#
+# Specifies whether or not to display the day spinner.
+# ------------------------------------------------------------------
+configbody iwidgets::Spindate::dayon {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -yearon
+#
+# Specifies whether or not to display the year spinner.
+# ------------------------------------------------------------------
+configbody iwidgets::Spindate::yearon {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -datemargin
+#
+# Specifies the margin space between the month and day spinners
+# and the day and year spinners.
+# ------------------------------------------------------------------
+configbody iwidgets::Spindate::datemargin {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -yeardigits
+#
+# Number of digits for year display, 2 or 4
+# ------------------------------------------------------------------
+configbody iwidgets::Spindate::yeardigits {
+ set clicks [clock seconds]
+
+ switch $itk_option(-yeardigits) {
+ "2" {
+ $itk_component(year) configure -width 2 -fixed 2
+ $itk_component(year) clear
+ $itk_component(year) insert 0 [clock format $clicks -format "%y"]
+ set _yearFormatStr "%y"
+ }
+
+ "4" {
+ $itk_component(year) configure -width 4 -fixed 4
+ $itk_component(year) clear
+ $itk_component(year) insert 0 [clock format $clicks -format "%Y"]
+ set _yearFormatStr "%Y"
+ }
+
+ default {
+ error "bad yeardigits option \"$itk_option(-yeardigits)\",\
+ should be 2 or 4"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -monthformat
+#
+# Format of month display, integers (1-12) or brief strings (Jan -
+# Dec), or full strings (January - December).
+# ------------------------------------------------------------------
+configbody iwidgets::Spindate::monthformat {
+ set clicks [clock seconds]
+
+ if {$itk_option(-monthformat) == "brief"} {
+ $itk_component(month) configure -width 3 -fixed 3
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $clicks -format "%b"]
+ set _monthFormatStr "%b"
+
+ } elseif {$itk_option(-monthformat) == "full"} {
+ $itk_component(month) configure -width 9 -fixed 9
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $clicks -format "%B"]
+ set _monthFormatStr "%B"
+
+ } elseif {$itk_option(-monthformat) == "integer"} {
+ $itk_component(month) configure -width 2 -fixed 2
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $clicks -format "%m"]
+ set _monthFormatStr "%m"
+
+ } else {
+ error "bad monthformat option\
+ \"$itk_option(-monthformat)\", should be\
+ \"integer\", \"brief\" or \"full\""
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: get ?format?
+#
+# Return the current contents of the spindate widget in one of
+# two formats string or as an integer clock value using the -string
+# and -clicks options respectively. The default is by string.
+# Reference the clock command for more information on obtaining dates
+# and their formats.
+# ------------------------------------------------------------------
+body iwidgets::Spindate::get {{format "-string"}} {
+ set month [$itk_component(month) get]
+ set day [$itk_component(day) get]
+ set year [$itk_component(year) get]
+
+ if {[regexp {[0-9]+} $month]} {
+ set datestr "$month/$day/$year"
+ } else {
+ set datestr "$day $month $year"
+ }
+
+ switch -- $format {
+ "-string" {
+ return $datestr
+ }
+ "-clicks" {
+ return [clock scan $datestr]
+ }
+ default {
+ error "bad format option \"$format\":\
+ should be -string or -clicks"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: show date
+#
+# Changes the currently displayed date to be that of the date
+# argument. The date may be specified either as a string or an
+# integer clock value. Reference the clock command for more
+# information on obtaining dates and their formats.
+# ------------------------------------------------------------------
+body iwidgets::Spindate::show {{date "now"}} {
+ #
+ # Convert the date to a clock clicks value.
+ #
+ if {$date == "now"} {
+ set seconds [clock seconds]
+ } else {
+ if {[catch {clock format $date}] == 0} {
+ set seconds $date
+ } elseif {[catch {set seconds [clock scan $date]}] != 0} {
+ error "bad date: \"$date\", must be a valid date\
+ string, clock clicks value or the keyword now"
+ }
+ }
+
+ #
+ # Display the month based on the -monthformat option.
+ #
+ switch $itk_option(-monthformat) {
+ "brief" {
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $seconds -format "%b"]
+ }
+ "full" {
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $seconds -format "%B"]
+ }
+ "integer" {
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $seconds -format "%m"]
+ }
+ }
+
+ #
+ # Display the day.
+ #
+ $itk_component(day) delete 0 end
+ $itk_component(day) insert end [clock format $seconds -format "%d"]
+
+ #
+ # Display the year based on the -yeardigits option.
+ #
+ switch $itk_option(-yeardigits) {
+ "2" {
+ $itk_component(year) delete 0 end
+ $itk_component(year) insert 0 [clock format $seconds -format "%y"]
+ }
+
+ "4" {
+ $itk_component(year) delete 0 end
+ $itk_component(year) insert 0 [clock format $seconds -format "%Y"]
+ }
+ }
+
+ return
+}
+
+# ----------------------------------------------------------------
+# PRIVATE METHOD: _spinMonth direction
+#
+# Increment or decrement month value. We need to get the values
+# for all three fields so we can make sure the day agrees with
+# the month. Should the current day be greater than the day for
+# the spun month, then the day is set to the last day for the
+# new month.
+# ----------------------------------------------------------------
+body iwidgets::Spindate::_spinMonth {direction} {
+ set month [$itk_component(month) get]
+ set day [$itk_component(day) get]
+ set year [$itk_component(year) get]
+
+ #
+ # There appears to be a bug in the Tcl clock command in that it
+ # can't scan a date like "12/31/1999 1 month" or any other date with
+ # a year above 2000, but it has no problem scanning "07/01/1998 1 month".
+ # So, we're going to play a game and increment by days until this
+ # is fixed in Tcl.
+ #
+ if {$direction == 1} {
+ set incrdays 32
+ set day 01
+ } else {
+ set incrdays -28
+ set day 28
+ }
+
+ if {[regexp {[0-9]+} $month]} {
+ set clicks [clock scan "$month/$day/$year $incrdays day"]
+ } else {
+ set clicks [clock scan "$day $month $year $incrdays day"]
+ }
+
+ $itk_component(month) clear
+ $itk_component(month) insert 0 \
+ [clock format $clicks -format $_monthFormatStr]
+
+ set lastday [_lastDay [$itk_component(month) get] $year]
+
+ if {$day > $lastday} {
+ $itk_component(day) clear
+ $itk_component(day) insert end $lastday
+ }
+}
+
+# ----------------------------------------------------------------
+# PRIVATE METHOD: _spinDay direction
+#
+# Increment or decrement day value. If the previous day was the
+# first, then set the new day to the last day for the current
+# month. If it was the last day of the month, change it to the
+# first. Otherwise, spin it to the next day.
+# ----------------------------------------------------------------
+body iwidgets::Spindate::_spinDay {direction} {
+ set month [$itk_component(month) get]
+ set day [$itk_component(day) get]
+ set year [$itk_component(year) get]
+ set lastday [_lastDay $month $year]
+ set currclicks [get -clicks]
+
+ $itk_component(day) delete 0 end
+
+ if {(($day == "01") || ($day == "1")) && ($direction == -1)} {
+ $itk_component(day) insert 0 $lastday
+ return
+ }
+
+ if {($day == $lastday) && ($direction == 1)} {
+ $itk_component(day) insert 0 "01"
+ return
+ }
+
+ set clicks [clock scan "$direction day" -base $currclicks]
+ $itk_component(day) insert 0 [clock format $clicks -format "%d"]
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _packDate when
+#
+# Pack the components of the date spinner. If "when" is "now", the
+# change is applied immediately. If it is "later" or it is not
+# specified, then the change is applied later, when the application
+# is idle.
+# ------------------------------------------------------------------
+body iwidgets::Spindate::_packDate {{when later}} {
+ if {$when == "later"} {
+ if {$_repack == ""} {
+ set _repack [after idle [code $this _packDate now]]
+ }
+ return
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ #
+ # Turn off the minsizes for all the rows and columns.
+ #
+ for {set i 0} {$i < 5} {incr i} {
+ grid rowconfigure $_interior $i -minsize 0
+ grid columnconfigure $_interior $i -minsize 0
+ }
+
+ #
+ # Get some boolean 1/0 values for the -monthon and -dayon options.
+ # We need this later so that Tcl doesn't complain about operands
+ # of || being strings.
+ #
+ set monthon [expr {$itk_option(-monthon) == "1"}]
+ set dayon [expr {$itk_option(-dayon) == "1"}]
+
+ set _repack ""
+
+ #
+ # Based on the orientation, use the grid to place the components into
+ # the proper rows and columns.
+ #
+ switch $itk_option(-orient) {
+ vertical {
+ set row -1
+
+ if {$itk_option(-monthon)} {
+ grid $itk_component(month) -row [incr row] -column 0 \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(month)
+ }
+
+ if {$itk_option(-dayon)} {
+ if {$itk_option(-dayon)} {
+ grid rowconfigure $_interior [incr row] \
+ -minsize $itk_option(-datemargin)
+ }
+
+ grid $itk_component(day) -row [incr row] -column 0 \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(day)
+ }
+
+ if {$itk_option(-yearon)} {
+ if {$monthon || $dayon} {
+ grid rowconfigure $_interior [incr row] \
+ -minsize $itk_option(-datemargin)
+ }
+
+ grid $itk_component(year) -row [incr row] -column 0 \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(year)
+ }
+
+ if {$itk_option(-labelpos) == "w"} {
+ iwidgets::Labeledwidget::alignlabels $itk_component(month) \
+ $itk_component(day) $itk_component(year)
+ }
+ }
+
+ horizontal {
+ set column -1
+
+ if {$itk_option(-monthon)} {
+ grid $itk_component(month) -row 0 -column [incr column] \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(month)
+ }
+
+ if {$itk_option(-dayon)} {
+ if {$itk_option(-monthon)} {
+ grid columnconfigure $_interior [incr column] \
+ -minsize $itk_option(-datemargin)
+ }
+
+ grid $itk_component(day) -row 0 -column [incr column] \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(day)
+ }
+
+ if {$itk_option(-yearon)} {
+ if {$monthon || $dayon} {
+ grid columnconfigure $_interior [incr column] \
+ -minsize $itk_option(-datemargin)
+ }
+
+ grid $itk_component(year) -row 0 -column [incr column] \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(year)
+ }
+
+ #
+ # Un-align labels.
+ #
+ $itk_component(month) configure -labelmargin 1
+ $itk_component(day) configure -labelmargin 1
+ $itk_component(year) configure -labelmargin 1
+ }
+
+ default {
+ error "bad orient option \"$itk_option(-orient)\", should\
+ be \"vertical\" or \"horizontal\""
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _lastDay month year
+#
+# Internal method which determines the last day of the month for
+# the given month and year. We start at 28 and go forward till
+# we fail. Crude but effective.
+# ------------------------------------------------------------------
+body iwidgets::Spindate::_lastDay {month year} {
+ set lastone 28
+
+ for {set lastone 28} {$lastone < 32} {incr lastone} {
+ if {[regexp {[0-9]+} $month]} {
+ if {[catch {clock scan "$month/[expr $lastone + 1]/$year"}] != 0} {
+ return $lastone
+ }
+ } else {
+ if {[catch {clock scan "[expr $lastone + 1] $month $year"}] != 0} {
+ return $lastone
+ }
+ }
+ }
+}