You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1019 lines
30 KiB
Plaintext
1019 lines
30 KiB
Plaintext
15 years ago
|
#
|
||
|
# Timefield
|
||
|
# ----------------------------------------------------------------------
|
||
|
# Implements a time entry field with adjustable built-in intelligence
|
||
|
# levels.
|
||
|
# ----------------------------------------------------------------------
|
||
|
# AUTHOR: John A. Tucker E-mail: jatucker@austin.dsccc.com
|
||
|
#
|
||
|
# @(#) $Id: timefield.itk,v 1.6 2001/08/17 19:05:44 smithc 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.
|
||
|
# ======================================================================
|
||
|
|
||
|
#
|
||
|
# Use option database to override default resources of base classes.
|
||
|
#
|
||
|
option add *Timefield.justify center widgetDefault
|
||
|
|
||
|
|
||
|
#
|
||
|
# Usual options.
|
||
|
#
|
||
|
itk::usual Timefield {
|
||
|
keep -background -borderwidth -cursor -foreground -highlightcolor \
|
||
|
-highlightthickness -labelfont -textbackground -textfont
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# TIMEFIELD
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::class iwidgets::Timefield {
|
||
|
|
||
|
inherit iwidgets::Labeledwidget
|
||
|
|
||
|
constructor {args} {}
|
||
|
|
||
|
itk_option define -childsitepos childSitePos Position e
|
||
|
itk_option define -command command Command {}
|
||
|
itk_option define -seconds seconds Seconds on
|
||
|
itk_option define -format format Format civilian
|
||
|
itk_option define -iq iq Iq high
|
||
|
itk_option define -gmt gmt GMT no
|
||
|
itk_option define -state state State normal
|
||
|
|
||
|
public {
|
||
|
method get {{format "-string"}}
|
||
|
method isvalid {}
|
||
|
method show {{time "now"}}
|
||
|
}
|
||
|
|
||
|
protected {
|
||
|
method _backwardCivilian {}
|
||
|
method _backwardMilitary {}
|
||
|
method _focusIn {}
|
||
|
method _forwardCivilian {}
|
||
|
method _forwardMilitary {}
|
||
|
method _keyPress {char sym state}
|
||
|
method _moveField {direction}
|
||
|
method _setField {field}
|
||
|
method _whichField {}
|
||
|
method _toggleAmPm {}
|
||
|
|
||
|
variable _cfield hour
|
||
|
variable _formatString "%r"
|
||
|
variable _fields {}
|
||
|
variable _numFields 4
|
||
|
variable _forward {}
|
||
|
variable _backward {}
|
||
|
variable _timeVar ""
|
||
|
|
||
|
common _militaryFields {hour minute second}
|
||
|
common _civilianFields {hour minute second ampm}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Provide a lowercased access method for the timefield class.
|
||
|
#
|
||
|
proc iwidgets::timefield {pathName args} {
|
||
|
uplevel iwidgets::Timefield $pathName $args
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# CONSTRUCTOR
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::constructor {args} {
|
||
|
component hull configure -borderwidth 0
|
||
|
|
||
|
#
|
||
|
# Create an entry field for entering the time.
|
||
|
#
|
||
|
itk_component add time {
|
||
|
entry $itk_interior.time
|
||
|
} {
|
||
|
keep -borderwidth -cursor -exportselection \
|
||
|
-foreground -highlightcolor -highlightthickness \
|
||
|
-insertbackground -justify -relief -textvariable
|
||
|
|
||
|
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 timefield event bindings for focus in and keypress events.
|
||
|
#
|
||
|
bind $itk_component(time) <FocusIn> [itcl::code $this _focusIn]
|
||
|
bind $itk_component(time) <KeyPress> [itcl::code $this _keyPress %A %K %s]
|
||
|
bind $itk_component(time) <1> "focus $itk_component(time); break"
|
||
|
|
||
|
#
|
||
|
# Disable some mouse button event bindings:
|
||
|
# Button Motion
|
||
|
# Double-Clicks
|
||
|
# Triple-Clicks
|
||
|
# Button2
|
||
|
#
|
||
|
bind $itk_component(time) <Button1-Motion> break
|
||
|
bind $itk_component(time) <Button2-Motion> break
|
||
|
bind $itk_component(time) <Double-Button> break
|
||
|
bind $itk_component(time) <Triple-Button> break
|
||
|
bind $itk_component(time) <2> break
|
||
|
|
||
|
#
|
||
|
# Initialize the widget based on the command line options.
|
||
|
#
|
||
|
eval itk_initialize $args
|
||
|
|
||
|
#
|
||
|
# Initialize the time to the current time.
|
||
|
#
|
||
|
show
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# OPTIONS
|
||
|
# ------------------------------------------------------------------
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# OPTION: -childsitepos
|
||
|
#
|
||
|
# Specifies the position of the child site in the widget. Valid
|
||
|
# locations are n, s, e, and w.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::configbody iwidgets::Timefield::childsitepos {
|
||
|
set parent [winfo parent $itk_component(time)]
|
||
|
|
||
|
switch $itk_option(-childsitepos) {
|
||
|
n {
|
||
|
grid $itk_component(dfchildsite) -row 0 -column 0 -sticky ew
|
||
|
grid $itk_component(time) -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(time) -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(time) -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(time) -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.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::configbody iwidgets::Timefield::command {}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# OPTION: -iq
|
||
|
#
|
||
|
# Specifies the level of intelligence to be shown in the actions
|
||
|
# taken by the time field during the processing of keypress events.
|
||
|
# Valid settings include high or low. With a high iq,
|
||
|
# the time prevents the user from typing in an invalid time. For
|
||
|
# example, if the current time is 05/31/1997 and the user changes
|
||
|
# the hour to 04, then the minute will be instantly modified for them
|
||
|
# to be 30. In addition, leap seconds are fully taken into account.
|
||
|
# A setting of low iq instructs the widget to do no validity checking
|
||
|
# at all during time entry. With a low iq level, it is assumed that
|
||
|
# the validity will be determined at a later time using the time's
|
||
|
# isvalid command.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::configbody iwidgets::Timefield::iq {
|
||
|
|
||
|
switch $itk_option(-iq) {
|
||
|
high - low {
|
||
|
|
||
|
}
|
||
|
default {
|
||
|
error "bad iq option \"$itk_option(-iq)\": should be high or low"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# OPTION: -format
|
||
|
#
|
||
|
# Specifies the time format displayed in the entry widget.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::configbody iwidgets::Timefield::format {
|
||
|
|
||
|
switch $itk_option(-format) {
|
||
|
civilian {
|
||
|
set _backward _backwardCivilian
|
||
|
set _forward _forwardCivilian
|
||
|
set _fields $_civilianFields
|
||
|
set _numFields 4
|
||
|
set _formatString "%r"
|
||
|
$itk_component(time) config -width 11
|
||
|
}
|
||
|
military {
|
||
|
set _backward _backwardMilitary
|
||
|
set _forward _forwardMilitary
|
||
|
set _fields $_militaryFields
|
||
|
set _numFields 3
|
||
|
set _formatString "%T"
|
||
|
$itk_component(time) config -width 8
|
||
|
}
|
||
|
default {
|
||
|
error "bad iq option \"$itk_option(-iq)\":\
|
||
|
should be civilian or military"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Update the current contents of the entry field to reflect
|
||
|
# the configured format.
|
||
|
#
|
||
|
show $_timeVar
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# OPTION: -gmt
|
||
|
#
|
||
|
# This option is used for GMT time. Must be a boolean value.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::configbody iwidgets::Timefield::gmt {
|
||
|
switch $itk_option(-gmt) {
|
||
|
0 - no - false - off { }
|
||
|
1 - yes - true - on { }
|
||
|
default {
|
||
|
error "bad gmt option \"$itk_option(-gmt)\": should be boolean"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# OPTION: -state
|
||
|
#
|
||
|
# Disable the
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::configbody iwidgets::Timefield::state {
|
||
|
switch -- $itk_option(-state) {
|
||
|
normal {
|
||
|
$itk_component(time) configure -state normal
|
||
|
}
|
||
|
disabled {
|
||
|
focus $itk_component(hull)
|
||
|
$itk_component(time) configure -state disabled
|
||
|
}
|
||
|
default {
|
||
|
error "Invalid value for -state: $itk_option(-state). Should be\
|
||
|
\"normal\" or \"disabled\"."
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# METHODS
|
||
|
# ------------------------------------------------------------------
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PUBLIC METHOD: get ?format?
|
||
|
#
|
||
|
# Return the current contents of the timefield 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 times and their
|
||
|
# formats.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::get {{format "-string"}} {
|
||
|
set _timeVar [$itk_component(time) get]
|
||
|
|
||
|
switch -- $format {
|
||
|
"-string" {
|
||
|
return $_timeVar
|
||
|
}
|
||
|
"-clicks" {
|
||
|
return [::clock scan $_timeVar -gmt $itk_option(-gmt)]
|
||
|
}
|
||
|
default {
|
||
|
error "bad format option \"$format\":\
|
||
|
should be -string or -clicks"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PUBLIC METHOD: show time
|
||
|
#
|
||
|
# Changes the currently displayed time to be that of the time
|
||
|
# argument. The time may be specified either as a string or an
|
||
|
# integer clock value. Reference the clock command for more
|
||
|
# information on obtaining times and their formats.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::show {{time "now"}} {
|
||
|
set icursor [$itk_component(time) index insert]
|
||
|
|
||
|
if {$time == {}} {
|
||
|
set time "now"
|
||
|
}
|
||
|
|
||
|
switch -regexp -- $time {
|
||
|
|
||
|
{^now$} {
|
||
|
set seconds [::clock seconds]
|
||
|
}
|
||
|
|
||
|
{^[0-9]+$} {
|
||
|
if { [catch {::clock format $time -gmt $itk_option(-gmt)}] } {
|
||
|
error "bad time: \"$time\", must be a valid time \
|
||
|
string, clock clicks value or the keyword now"
|
||
|
}
|
||
|
set seconds $time
|
||
|
}
|
||
|
|
||
|
default {
|
||
|
if {[catch {set seconds [::clock scan $time -gmt $itk_option(-gmt)]}]} {
|
||
|
error "bad time: \"$time\", must be a valid time \
|
||
|
string, clock clicks value or the keyword now"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set _timeVar [::clock format $seconds -format $_formatString \
|
||
|
-gmt $itk_option(-gmt)]
|
||
|
|
||
|
$itk_component(time) delete 0 end
|
||
|
$itk_component(time) insert end $_timeVar
|
||
|
$itk_component(time) icursor $icursor
|
||
|
|
||
|
return $_timeVar
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PUBLIC METHOD: isvalid
|
||
|
#
|
||
|
# Returns a boolean indication of the validity of the currently
|
||
|
# displayed time value. For example, 09:59::59 is valid whereas
|
||
|
# 26:59:59 is invalid.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::isvalid {} {
|
||
|
set _timeVar [$itk_component(time) get]
|
||
|
return [expr {([catch {::clock scan $_timeVar -gmt $itk_option(-gmt)}] == 0)}]
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# 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.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_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.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_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.
|
||
|
#
|
||
|
set _cfield [_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 minute, hour, and second.
|
||
|
#
|
||
|
set inValid 0
|
||
|
set icursor [$itk_component(time) index insert]
|
||
|
set lastField [lindex $_fields end]
|
||
|
|
||
|
set prevtime $_timeVar
|
||
|
regexp {^([0-9])([0-9]):([0-9])([0-9]):([0-9])([0-9]).*$} \
|
||
|
$_timeVar dummy \
|
||
|
hour1 hour2 minute1 minute2 second1 second2
|
||
|
set hour "$hour1$hour2"
|
||
|
set minute "$minute1$minute2"
|
||
|
set second "$second1$second2"
|
||
|
|
||
|
#
|
||
|
# 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 6 characters. If
|
||
|
# so ring the bell and break.
|
||
|
#
|
||
|
if {![catch {expr {int($char)}}]} {
|
||
|
|
||
|
# If we are currently in the hour 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 the current format is military, then
|
||
|
# validate the hour field which can be [00 - 23]
|
||
|
#
|
||
|
switch $_cfield {
|
||
|
hour {
|
||
|
if {$itk_option(-iq) == "low"} {
|
||
|
$itk_component(time) delete $icursor
|
||
|
$itk_component(time) insert $icursor $char
|
||
|
|
||
|
} elseif {$itk_option(-format) == "military"} {
|
||
|
if {$icursor == 0} {
|
||
|
#
|
||
|
# if the digit is less than 2, then
|
||
|
# the second hour digit is valid for 0-9
|
||
|
#
|
||
|
if {$char < 2} {
|
||
|
$itk_component(time) delete 0 1
|
||
|
$itk_component(time) insert 0 $char
|
||
|
|
||
|
#
|
||
|
# if the digit is equal to 2, then
|
||
|
# the second hour digit is valid for 0-3
|
||
|
#
|
||
|
} elseif {$char == 2} {
|
||
|
$itk_component(time) delete 0 1
|
||
|
$itk_component(time) insert 0 $char
|
||
|
|
||
|
if {$hour2 > 3} {
|
||
|
$itk_component(time) delete 1 2
|
||
|
$itk_component(time) insert 1 "0"
|
||
|
$itk_component(time) icursor 1
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# if the digit is greater than 2, then
|
||
|
# set the first hour digit to 0 and the
|
||
|
# second hour digit to the value.
|
||
|
#
|
||
|
} elseif {$char > 2} {
|
||
|
$itk_component(time) delete 0 2
|
||
|
$itk_component(time) insert 0 "0$char"
|
||
|
set icursor 1
|
||
|
} else {
|
||
|
set inValid 1
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# if the insertion cursor is for the second hour digit, then
|
||
|
# format is military, then it can only be valid if the first
|
||
|
# hour digit is less than 2 or the new digit is less than 4
|
||
|
#
|
||
|
} else {
|
||
|
if {$hour1 < 2 || $char < 4} {
|
||
|
$itk_component(time) delete 1 2
|
||
|
$itk_component(time) insert 1 $char
|
||
|
} else {
|
||
|
set inValid 1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# The format is civilian, so we need to
|
||
|
# validate the hour field which can be [01 - 12]
|
||
|
#
|
||
|
} else {
|
||
|
if {$icursor == 0} {
|
||
|
#
|
||
|
# if the digit is 0, then
|
||
|
# the second hour digit is valid for 1-9
|
||
|
# so just insert it.
|
||
|
#
|
||
|
if {$char == 0 && $hour2 != 0} {
|
||
|
$itk_component(time) delete 0 1
|
||
|
$itk_component(time) insert 0 $char
|
||
|
|
||
|
#
|
||
|
# if the digit is equal to 1, then
|
||
|
# the second hour digit is valid for 0-2
|
||
|
#
|
||
|
} elseif {$char == 1} {
|
||
|
$itk_component(time) delete 0 1
|
||
|
$itk_component(time) insert 0 $char
|
||
|
|
||
|
if {$hour2 > 2} {
|
||
|
$itk_component(time) delete 1 2
|
||
|
$itk_component(time) insert 1 0
|
||
|
set icursor 1
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# if the digit is greater than 1, then
|
||
|
# set the first hour digit to 0 and the
|
||
|
# second hour digit to the value.
|
||
|
#
|
||
|
} elseif {$char > 1} {
|
||
|
$itk_component(time) delete 0 2
|
||
|
$itk_component(time) insert 0 "0$char"
|
||
|
set icursor 1
|
||
|
|
||
|
} else {
|
||
|
set inValid 1
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# The insertion cursor is at the second hour digit, so
|
||
|
# it can only be valid if the firs thour digit is 0
|
||
|
# or the new digit is less than or equal to 2
|
||
|
#
|
||
|
} else {
|
||
|
if {$hour1 == 0 || $char <= 2} {
|
||
|
$itk_component(time) delete 1 2
|
||
|
$itk_component(time) insert 1 $char
|
||
|
} else {
|
||
|
set inValid 1
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if {$inValid} {
|
||
|
bell
|
||
|
} elseif {$icursor == 1} {
|
||
|
_setField minute
|
||
|
}
|
||
|
}
|
||
|
|
||
|
minute {
|
||
|
if {$itk_option(-iq) == "low" || $char < 6 || $icursor == 4} {
|
||
|
$itk_component(time) delete $icursor
|
||
|
$itk_component(time) insert $icursor $char
|
||
|
} elseif {$itk_option(-iq) == "high"} {
|
||
|
if {$char > 5} {
|
||
|
$itk_component(time) delete 3 5
|
||
|
$itk_component(time) insert 3 "0$char"
|
||
|
set icursor 4
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if {$icursor == 4} {
|
||
|
_setField second
|
||
|
}
|
||
|
}
|
||
|
|
||
|
second {
|
||
|
if {$itk_option(-iq) == "low" || $char < 6 || $icursor == 7} {
|
||
|
$itk_component(time) delete $icursor
|
||
|
$itk_component(time) insert $icursor $char
|
||
|
|
||
|
} elseif {$itk_option(-iq) == "high"} {
|
||
|
if {$char > 5} {
|
||
|
$itk_component(time) delete 6 8
|
||
|
$itk_component(time) insert 6 "0$char"
|
||
|
set icursor 7
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if {$icursor == 7} {
|
||
|
_moveField forward
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set _timeVar [$itk_component(time) get]
|
||
|
return -code break
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Process the plus and the up arrow keys. They both yield the same
|
||
|
# effect, they increment the minute by one.
|
||
|
#
|
||
|
switch $sym {
|
||
|
p - P {
|
||
|
if {$itk_option(-format) == "civilian"} {
|
||
|
$itk_component(time) delete 9 10
|
||
|
$itk_component(time) insert 9 P
|
||
|
_setField hour
|
||
|
}
|
||
|
}
|
||
|
|
||
|
a - A {
|
||
|
if {$itk_option(-format) == "civilian"} {
|
||
|
$itk_component(time) delete 9 10
|
||
|
$itk_component(time) insert 9 A
|
||
|
_setField hour
|
||
|
}
|
||
|
}
|
||
|
|
||
|
plus - Up {
|
||
|
if {$_cfield == "ampm"} {
|
||
|
_toggleAmPm
|
||
|
} else {
|
||
|
set newclicks [::clock scan "$prevtime 1 $_cfield"]
|
||
|
show [::clock format $newclicks -format $_formatString]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
minus - Down {
|
||
|
#
|
||
|
# Process the minus and the down arrow keys which decrement the value
|
||
|
# of the field in which the cursor is currently positioned.
|
||
|
#
|
||
|
if {$_cfield == "ampm"} {
|
||
|
_toggleAmPm
|
||
|
} else {
|
||
|
set newclicks [::clock scan "$prevtime 1 $_cfield ago"]
|
||
|
show [::clock format $newclicks -format $_formatString]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Tab {
|
||
|
#
|
||
|
# A tab key moves the "hour:minute:second" field forward by one unless
|
||
|
# the current field is the second. In that case we'll let tab
|
||
|
# do what is supposed to and pass the focus onto the next widget.
|
||
|
#
|
||
|
if {$state == 0} {
|
||
|
|
||
|
if {($itk_option(-format) == "civilian" && $_cfield == $lastField)} {
|
||
|
_setField hour
|
||
|
return -code continue
|
||
|
}
|
||
|
_moveField forward
|
||
|
|
||
|
#
|
||
|
# A ctrl-tab key moves the hour:minute:second field backwards by one
|
||
|
# unless the current field is the hour. In that case we'll let
|
||
|
# tab take the focus to a previous widget.
|
||
|
#
|
||
|
} elseif {$state == 4} {
|
||
|
if {$_cfield == "hour"} {
|
||
|
_setField hour
|
||
|
return -code continue
|
||
|
}
|
||
|
_moveField backward
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Right {
|
||
|
#
|
||
|
# A right arrow key moves the insert cursor to the right one.
|
||
|
#
|
||
|
$_forward
|
||
|
}
|
||
|
|
||
|
Left - BackSpace - Delete {
|
||
|
#
|
||
|
# A left arrow, backspace, or delete key moves the insert cursor
|
||
|
# to the left one. This is what you expect for the left arrow
|
||
|
# and since the whole widget always operates in overstrike mode,
|
||
|
# it makes the most sense for backspace and delete to do the same.
|
||
|
#
|
||
|
$_backward
|
||
|
}
|
||
|
|
||
|
Return {
|
||
|
#
|
||
|
# A Return key invokes the optionally specified command option.
|
||
|
#
|
||
|
uplevel #0 $itk_option(-command)
|
||
|
}
|
||
|
|
||
|
default {
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -code break
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PROTECTED METHOD: _toggleAmPm
|
||
|
#
|
||
|
# Internal method which toggles the displayed time
|
||
|
# between "AM" and "PM" when format is "civilian".
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_toggleAmPm {} {
|
||
|
set firstChar [string index $_timeVar 9]
|
||
|
$itk_component(time) delete 9 10
|
||
|
$itk_component(time) insert 9 [expr {($firstChar == "A") ? "P" : "A"}]
|
||
|
$itk_component(time) icursor 9
|
||
|
set _timeVar [$itk_component(time) get]
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PROTECTED METHOD: _setField field
|
||
|
#
|
||
|
# Adjusts the current field to be that of the argument, setting the
|
||
|
# insert cursor appropriately.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_setField {field} {
|
||
|
|
||
|
# Move the position of the cursor to the first character of the
|
||
|
# field given by the argument:
|
||
|
#
|
||
|
# Field First Character Index
|
||
|
# ----- ---------------------
|
||
|
# hour 0
|
||
|
# minute 3
|
||
|
# second 6
|
||
|
# ampm 9
|
||
|
#
|
||
|
switch $field {
|
||
|
hour {
|
||
|
$itk_component(time) icursor 0
|
||
|
}
|
||
|
minute {
|
||
|
$itk_component(time) icursor 3
|
||
|
}
|
||
|
second {
|
||
|
$itk_component(time) icursor 6
|
||
|
}
|
||
|
ampm {
|
||
|
if {$itk_option(-format) == "military"} {
|
||
|
error "bad field: \"$field\", must be hour, minute or second"
|
||
|
}
|
||
|
$itk_component(time) icursor 9
|
||
|
}
|
||
|
default {
|
||
|
if {$itk_option(-format) == "military"} {
|
||
|
error "bad field: \"$field\", must be hour, minute or second"
|
||
|
} else {
|
||
|
error "bad field: \"$field\", must be hour, minute, second or ampm"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set _cfield $field
|
||
|
|
||
|
return $_cfield
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PROTECTED METHOD: _moveField
|
||
|
#
|
||
|
# Moves the cursor one field forward or backward.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_moveField {direction} {
|
||
|
|
||
|
# Since the value "_fields" list variable is always either value:
|
||
|
# military => {hour minute second}
|
||
|
# civilian => {hour minute second ampm}
|
||
|
#
|
||
|
# the index of the previous or next field index can be determined
|
||
|
# by subtracting or adding 1 to current the index, respectively.
|
||
|
#
|
||
|
set index [lsearch $_fields $_cfield]
|
||
|
expr {($direction == "forward") ? [incr index] : [incr index -1]}
|
||
|
|
||
|
if {$index == $_numFields} {
|
||
|
set index 0
|
||
|
} elseif {$index < 0} {
|
||
|
set index [expr {$_numFields-1}]
|
||
|
}
|
||
|
|
||
|
_setField [lindex $_fields $index]
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PROTECTED METHOD: _whichField
|
||
|
#
|
||
|
# Returns the current field that the cursor is positioned within.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_whichField {} {
|
||
|
|
||
|
# Return the current field based on the position of the cursor.
|
||
|
#
|
||
|
# Field Index
|
||
|
# ----- -----
|
||
|
# hour 0,1
|
||
|
# minute 3,4
|
||
|
# second 6,7
|
||
|
# ampm 9,10
|
||
|
#
|
||
|
set icursor [$itk_component(time) index insert]
|
||
|
switch $icursor {
|
||
|
0 - 1 {
|
||
|
set _cfield hour
|
||
|
}
|
||
|
3 - 4 {
|
||
|
set _cfield minute
|
||
|
}
|
||
|
6 - 7 {
|
||
|
set _cfield second
|
||
|
}
|
||
|
9 - 10 {
|
||
|
set _cfield ampm
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $_cfield
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PROTECTED METHOD: _forwardCivilian
|
||
|
#
|
||
|
# Internal method which moves the cursor forward by one character
|
||
|
# jumping over the slashes and wrapping.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_forwardCivilian {} {
|
||
|
|
||
|
#
|
||
|
# If the insertion cursor is at the second digit
|
||
|
# of either the hour, minute or second field, then
|
||
|
# move the cursor to the first digit of the right-most field.
|
||
|
#
|
||
|
# else move the insertion cursor right one character
|
||
|
#
|
||
|
set icursor [$itk_component(time) index insert]
|
||
|
switch $icursor {
|
||
|
1 {
|
||
|
_setField minute
|
||
|
}
|
||
|
4 {
|
||
|
_setField second
|
||
|
}
|
||
|
7 {
|
||
|
_setField ampm
|
||
|
}
|
||
|
9 - 10 {
|
||
|
_setField hour
|
||
|
}
|
||
|
default {
|
||
|
$itk_component(time) icursor [expr {$icursor+1}]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PROTECTED METHOD: _forwardMilitary
|
||
|
#
|
||
|
# Internal method which moves the cursor forward by one character
|
||
|
# jumping over the slashes and wrapping.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_forwardMilitary {} {
|
||
|
|
||
|
#
|
||
|
# If the insertion cursor is at the second digit of either
|
||
|
# the hour, minute or second field, then move the cursor to
|
||
|
# the first digit of the right-most field.
|
||
|
#
|
||
|
# else move the insertion cursor right one character
|
||
|
#
|
||
|
set icursor [$itk_component(time) index insert]
|
||
|
switch $icursor {
|
||
|
1 {
|
||
|
_setField minute
|
||
|
}
|
||
|
4 {
|
||
|
_setField second
|
||
|
}
|
||
|
7 {
|
||
|
_setField hour
|
||
|
}
|
||
|
default {
|
||
|
$itk_component(time) icursor [expr {$icursor+1}]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PROTECTED METHOD: _backwardCivilian
|
||
|
#
|
||
|
# Internal method which moves the cursor backward by one character
|
||
|
# jumping over the ":" and wrapping.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_backwardCivilian {} {
|
||
|
|
||
|
#
|
||
|
# If the insertion cursor is at the first character
|
||
|
# of either the minute or second field or at the ampm
|
||
|
# field, then move the cursor to the second character
|
||
|
# of the left-most field.
|
||
|
#
|
||
|
# else if the insertion cursor is at the first digit of the
|
||
|
# hour field, then move the cursor to the first character
|
||
|
# of the ampm field.
|
||
|
#
|
||
|
# else move the insertion cursor left one character
|
||
|
#
|
||
|
set icursor [$itk_component(time) index insert]
|
||
|
switch $icursor {
|
||
|
9 {
|
||
|
_setField second
|
||
|
$itk_component(time) icursor 7
|
||
|
}
|
||
|
6 {
|
||
|
_setField minute
|
||
|
$itk_component(time) icursor 4
|
||
|
}
|
||
|
3 {
|
||
|
_setField hour
|
||
|
$itk_component(time) icursor 1
|
||
|
}
|
||
|
0 {
|
||
|
_setField ampm
|
||
|
$itk_component(time) icursor 9
|
||
|
}
|
||
|
default {
|
||
|
$itk_component(time) icursor [expr {$icursor-1}]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# ------------------------------------------------------------------
|
||
|
# PROTECTED METHOD: _backwardMilitary
|
||
|
#
|
||
|
# Internal method which moves the cursor backward by one character
|
||
|
# jumping over the slashes and wrapping.
|
||
|
# ------------------------------------------------------------------
|
||
|
itcl::body iwidgets::Timefield::_backwardMilitary {} {
|
||
|
|
||
|
#
|
||
|
# If the insertion cursor is at the first digit of either
|
||
|
# the minute or second field, then move the cursor to the
|
||
|
# second character of the left-most field.
|
||
|
#
|
||
|
# else if the insertion cursor is at the first digit of the
|
||
|
# hour field, then move the cursor to the second digit
|
||
|
# of the second field.
|
||
|
#
|
||
|
# else move the insertion cursor left one character
|
||
|
#
|
||
|
set icursor [$itk_component(time) index insert]
|
||
|
switch $icursor {
|
||
|
6 {
|
||
|
_setField minute
|
||
|
$itk_component(time) icursor 4
|
||
|
}
|
||
|
3 {
|
||
|
_setField hour
|
||
|
$itk_component(time) icursor 1
|
||
|
}
|
||
|
0 {
|
||
|
_setField second
|
||
|
$itk_component(time) icursor 7
|
||
|
}
|
||
|
default {
|
||
|
$itk_component(time) icursor [expr {$icursor-1}]
|
||
|
}
|
||
|
}
|
||
|
}
|