summaryrefslogtreecommitdiff
path: root/iwidgets/generic/timefield.itk
diff options
context:
space:
mode:
Diffstat (limited to 'iwidgets/generic/timefield.itk')
-rw-r--r--iwidgets/generic/timefield.itk1018
1 files changed, 1018 insertions, 0 deletions
diff --git a/iwidgets/generic/timefield.itk b/iwidgets/generic/timefield.itk
new file mode 100644
index 00000000000..ee99e383059
--- /dev/null
+++ b/iwidgets/generic/timefield.itk
@@ -0,0 +1,1018 @@
+#
+# Timefield
+# ----------------------------------------------------------------------
+# Implements a time entry field with adjustable built-in intelligence
+# levels.
+# ----------------------------------------------------------------------
+# AUTHOR: John A. Tucker E-mail: jatucker@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.
+# ======================================================================
+
+#
+# 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}]
+ }
+ }
+}