📄 datefield.itk
字号:
## Datefield# ----------------------------------------------------------------------# Implements a date entry field with adjustable built-in intelligence# levels.# ----------------------------------------------------------------------# AUTHOR: Mark L. Ulferts E-mail: mulferts@austin.dsccc.com## @(#) $Id: datefield.itk,v 1.1 2003/02/05 10:54:05 mdejong Exp $# ----------------------------------------------------------------------# 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.# ======================================================================## Usual options.#itk::usual Datefield { keep -background -borderwidth -cursor -foreground -highlightcolor \ -highlightthickness -labelfont -textbackground -textfont}# ------------------------------------------------------------------# DATEFIELD# ------------------------------------------------------------------class iwidgets::Datefield { inherit iwidgets::Labeledwidget constructor {args} {} itk_option define -childsitepos childSitePos Position e itk_option define -command command Command {} itk_option define -iq iq Iq high public method get {{format "-string"}} public method isvalid {} public method show {{date now}} protected method _backward {} protected method _focusIn {} protected method _forward {} protected method _keyPress {char sym state} protected method _lastDay {month year} protected method _moveField {direction} protected method _setField {field} protected method _whichField {} protected variable _cfield "month" protected variable _fields {month day year}}## Provide a lowercased access method for the datefield class.# proc ::iwidgets::datefield {pathName args} { uplevel ::iwidgets::Datefield $pathName $args}## Use option database to override default resources of base classes.#option add *Datefield.justify center widgetDefault# ------------------------------------------------------------------# CONSTRUCTOR# ------------------------------------------------------------------body iwidgets::Datefield::constructor {args} { component hull configure -borderwidth 0 # # Create an entry field for entering the date. # itk_component add date { entry $itk_interior.date -width 10 } { keep -borderwidth -cursor -exportselection \ -foreground -highlightcolor -highlightthickness \ -insertbackground -justify -relief -state rename -font -textfont textFont Font rename -highlightbackground -background background Background rename -background -textbackground textBackground Background } # # Create the child site widget. # itk_component add -protected dfchildsite { frame $itk_interior.dfchildsite } set itk_interior $itk_component(dfchildsite) # # Add datefield event bindings for focus in and keypress events. # bind $itk_component(date) <FocusIn> [code $this _focusIn] bind $itk_component(date) <KeyPress> [code $this _keyPress %A %K %s] # # Disable some mouse button event bindings: # Button Motion # Double-Clicks # Triple-Clicks # Button2 # bind $itk_component(date) <Button1-Motion> break bind $itk_component(date) <Button2-Motion> break bind $itk_component(date) <Double-Button> break bind $itk_component(date) <Triple-Button> break bind $itk_component(date) <2> break # # Initialize the widget based on the command line options. # eval itk_initialize $args # # Initialize the date to the current date. # $itk_component(date) delete 0 end $itk_component(date) insert end \ [clock format [clock seconds] -format "%m/%d/%Y"]}# ------------------------------------------------------------------# OPTIONS# ------------------------------------------------------------------# ------------------------------------------------------------------# OPTION: -childsitepos## Specifies the position of the child site in the widget. Valid# locations are n, s, e, and w.# ------------------------------------------------------------------configbody iwidgets::Datefield::childsitepos { set parent [winfo parent $itk_component(date)] switch $itk_option(-childsitepos) { n { grid $itk_component(dfchildsite) -row 0 -column 0 -sticky ew grid $itk_component(date) -row 1 -column 0 -sticky nsew grid rowconfigure $parent 0 -weight 0 grid rowconfigure $parent 1 -weight 1 grid columnconfigure $parent 0 -weight 1 grid columnconfigure $parent 1 -weight 0 } e { grid $itk_component(dfchildsite) -row 0 -column 1 -sticky ns grid $itk_component(date) -row 0 -column 0 -sticky nsew grid rowconfigure $parent 0 -weight 1 grid rowconfigure $parent 1 -weight 0 grid columnconfigure $parent 0 -weight 1 grid columnconfigure $parent 1 -weight 0 } s { grid $itk_component(dfchildsite) -row 1 -column 0 -sticky ew grid $itk_component(date) -row 0 -column 0 -sticky nsew grid rowconfigure $parent 0 -weight 1 grid rowconfigure $parent 1 -weight 0 grid columnconfigure $parent 0 -weight 1 grid columnconfigure $parent 1 -weight 0 } w { grid $itk_component(dfchildsite) -row 0 -column 0 -sticky ns grid $itk_component(date) -row 0 -column 1 -sticky nsew grid rowconfigure $parent 0 -weight 1 grid rowconfigure $parent 1 -weight 0 grid columnconfigure $parent 0 -weight 0 grid columnconfigure $parent 1 -weight 1 } default { error "bad childsite option\ \"$itk_option(-childsitepos)\":\ should be n, e, s, or w" } }}# ------------------------------------------------------------------# OPTION: -command## Command invoked upon detection of return key press event.# ------------------------------------------------------------------configbody iwidgets::Datefield::command {}# ------------------------------------------------------------------# OPTION: -iq## Specifies the level of intelligence to be shown in the actions# taken by the date field during the processing of keypress events.# Valid settings include high, average, and low. With a high iq,# the date prevents the user from typing in an invalid date. For # example, if the current date is 05/31/1997 and the user changes# the month to 04, then the day will be instantly modified for them # to be 30. In addition, leap years are fully taken into account.# With average iq, the month is limited to the values of 01-12, but# it is possible to type in an invalid day. A setting of low iq# instructs the widget to do no validity checking at all during# date entry. With both average and low iq levels, it is assumed# that the validity will be determined at a later time using the# date's isvalid command.# ------------------------------------------------------------------configbody iwidgets::Datefield::iq { switch $itk_option(-iq) { high - average - low { } default { error "bad iq option \"$itk_option(-iq)\":\ should be high, average or low" } }}# ------------------------------------------------------------------# METHODS# ------------------------------------------------------------------# ------------------------------------------------------------------# PUBLIC METHOD: get ?format?## Return the current contents of the datefield 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::Datefield::get {{format "-string"}} { set datestr [$itk_component(date) get] 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::Datefield::show {{date "now"}} { 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" } } $itk_component(date) delete 0 end $itk_component(date) insert end [clock format $seconds -format "%m/%d/%Y"] _setField month return}# ------------------------------------------------------------------# PUBLIC METHOD: isvalid## Returns a boolean indication of the validity of the currently# displayed date value. For example, 3/3/1960 is valid whereas# 02/29/1997 is invalid.# ------------------------------------------------------------------body iwidgets::Datefield::isvalid {} { if {[catch {clock scan [$itk_component(date) get]}] != 0} { return 0 } else { return 1 }}# ------------------------------------------------------------------# PROTECTED METHOD: _focusIn## This method is bound to the <FocusIn> event. It resets the # insert cursor and field settings to be back to their last known# positions.# ------------------------------------------------------------------body iwidgets::Datefield::_focusIn {} { _setField $_cfield}# ------------------------------------------------------------------# PROTECTED METHOD: _keyPress ## This method is the workhorse of the class. It is bound to the# <KeyPress> event and controls the processing of all key strokes.# ------------------------------------------------------------------body iwidgets::Datefield::_keyPress {char sym state} { # # Determine which field we are in currently. This is needed # since the user may have moved to this position via a mouse # selection and so it would not be in the position we last # knew it to be. # _whichField # # Set up a few basic variables we'll be needing throughout the # rest of the method such as the position of the insert cursor # and the currently displayed day, month, and year. # set icursor [$itk_component(date) index insert] set splist [split [$itk_component(date) get] "/"] set month [lindex $splist 0] set day [lindex $splist 1] set year [lindex $splist 2] # # Process numeric keystrokes. This involes a fair amount of # processing with step one being to check and make sure we # aren't attempting to insert more that 10 characters. If # so ring the bell and break. # if {[regexp {[0-9]} $char]} { if {[$itk_component(date) index insert] == 10} { bell return -code break } # # If we are currently in the month field then we process the # number entered based on the cursor position. If we are at # at the first position and our iq is low, then accept any # input. # if {$_cfield == "month"} { if {[$itk_component(date) index insert] == 0} { if {$itk_option(-iq) == "low"} { $itk_component(date) delete 0 $itk_component(date) insert 0 $char } else { # # Otherwise, we're slightly smarter. If the number # is less than two insert it at position zero. If # this makes the month greater than twelve, set the # number at position one to zero which makes in # effect puts the month back in range. # regsub {([0-9])([0-9])} $month "$char\\2" month2b if {$char < 2} { $itk_component(date) delete 0 $itk_component(date) insert 0 $char if {$month2b > 12} { $itk_component(date) delete 1 $itk_component(date) insert 1 0 $itk_component(date) icursor 1 } elseif {$month2b == "00"} { $itk_component(date) delete 1 $itk_component(date) insert 1 1 $itk_component(date) icursor 1 } # # Finally, if the number is greater than one we'll # assume that they really mean to be entering a zero # followed by their number, do so for them, and # proceed to skip to the next field which is the # day field. # } else { $itk_component(date) delete 0 2 $itk_component(date) insert 0 0$char _setField day } } # # Else, we're at cursor position one. Again, if we aren't # too smart, let them enter anything. Otherwise, if the # number makes the month exceed twelve, set the month to # zero followed by their number to get it back into range. # } else { regsub {([0-9])([0-9])} $month "\\1$char" month2b if {$itk_option(-iq) == "low"} { $itk_component(date) delete 1 $itk_component(date) insert 1 $char } else { if {$month2b > 12} { $itk_component(date) delete 0 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -