home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 December / PCWorld_2000-12_cd.bin / Komunikace / Comanche / comanche.exe / lib / iwidgets3.0.0 / scripts / timefield.itk < prev    next >
Text File  |  1999-02-24  |  29KB  |  976 lines

  1. #
  2. # Timefield
  3. # ----------------------------------------------------------------------
  4. # Implements a time entry field with adjustable built-in intelligence
  5. # levels.
  6. # ----------------------------------------------------------------------
  7. #   AUTHOR:  John A. Tucker          E-mail: jatucker@austin.dsccc.com
  8. #
  9. #   @(#) $Id: timefield.itk,v 1.1 1998/07/27 18:53:20 stanton Exp $
  10. # ----------------------------------------------------------------------
  11. #            Copyright (c) 1997 DSC Technologies Corporation
  12. # ======================================================================
  13. # Permission to use, copy, modify, distribute and license this software 
  14. # and its documentation for any purpose, and without fee or written 
  15. # agreement with DSC, is hereby granted, provided that the above copyright 
  16. # notice appears in all copies and that both the copyright notice and 
  17. # warranty disclaimer below appear in supporting documentation, and that 
  18. # the names of DSC Technologies Corporation or DSC Communications 
  19. # Corporation not be used in advertising or publicity pertaining to the 
  20. # software without specific, written prior permission.
  21. # DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
  22. # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
  23. # INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
  24. # AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, 
  25. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL 
  26. # DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
  27. # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
  28. # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
  29. # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
  30. # SOFTWARE.
  31. # ======================================================================
  32.  
  33. #
  34. # Use option database to override default resources of base classes.
  35. #
  36. option add *Timefield.justify center widgetDefault
  37.  
  38.  
  39. #
  40. # Usual options.
  41. #
  42. itk::usual Timefield {
  43.     keep -background -borderwidth -cursor -foreground -highlightcolor \
  44.        -highlightthickness -labelfont -textbackground -textfont
  45. }
  46.  
  47. # ------------------------------------------------------------------
  48. #                               TIMEFIELD
  49. # ------------------------------------------------------------------
  50. class iwidgets::Timefield {
  51.  
  52.     inherit iwidgets::Labeledwidget 
  53.     
  54.     constructor {args} {}
  55.  
  56.     itk_option define -childsitepos childSitePos Position e
  57.     itk_option define -command command Command {}
  58.     itk_option define -seconds seconds Seconds on
  59.     itk_option define -format format Format civilian
  60.     itk_option define -iq iq Iq high
  61.  
  62.     public {
  63.       method get {{format "-string"}}
  64.       method isvalid {}
  65.       method show {{time "now"}}
  66.     }
  67.  
  68.     protected {
  69.       method _backwardCivilian {}
  70.       method _backwardMilitary {}
  71.       method _focusIn {}
  72.       method _forwardCivilian {}
  73.       method _forwardMilitary {}
  74.       method _keyPress {char sym state}
  75.       method _moveField {direction}
  76.       method _setField {field}
  77.       method _whichField {}
  78.       method _toggleAmPm {}
  79.  
  80.       variable _cfield hour
  81.       variable _formatString "%r"
  82.       variable _fields {}
  83.       variable _numFields 4
  84.       variable _forward {}
  85.       variable _backward {}
  86.  
  87.       common _militaryFields {hour minute second}
  88.       common _civilianFields {hour minute second ampm}
  89.  
  90.       common _timeVar
  91.     }
  92. }
  93.  
  94. #
  95. # Provide a lowercased access method for the timefield class.
  96. proc iwidgets::timefield {pathName args} {
  97.     uplevel iwidgets::Timefield $pathName $args
  98. }
  99.  
  100. # ------------------------------------------------------------------
  101. #                        CONSTRUCTOR
  102. # ------------------------------------------------------------------
  103. body iwidgets::Timefield::constructor {args} {
  104.     component hull configure -borderwidth 0
  105.     
  106.     set _timeVar($this) ""
  107.  
  108.     #
  109.     # Create an entry field for entering the time.
  110.     #
  111.     itk_component add time {
  112.       entry $itk_interior.time \
  113.             -textvariable [scope _timeVar($this)]
  114.     } {
  115.       keep -borderwidth -cursor -exportselection \
  116.           -foreground -highlightcolor -highlightthickness \
  117.           -insertbackground -justify -relief
  118.       
  119.       rename -font -textfont textFont Font
  120.       rename -highlightbackground -background background Background
  121.       rename -background -textbackground textBackground Background
  122.     }
  123.  
  124.     #
  125.     # Create the child site widget.
  126.     #
  127.     itk_component add -protected dfchildsite {
  128.       frame $itk_interior.dfchildsite
  129.     } 
  130.     set itk_interior $itk_component(dfchildsite)
  131.     
  132.     #
  133.     # Add timefield event bindings for focus in and keypress events.
  134.     #
  135.     bind $itk_component(time) <FocusIn>   [code $this _focusIn]
  136.     bind $itk_component(time) <KeyPress>  [code $this _keyPress %A %K %s]
  137.  
  138.     #
  139.     # Disable some mouse button event bindings:
  140.     #   Button Motion
  141.     #   Double-Clicks
  142.     #   Triple-Clicks
  143.     #   Button2
  144.     #
  145.     bind $itk_component(time) <Button1-Motion>    break
  146.     bind $itk_component(time) <Button2-Motion>    break
  147.     bind $itk_component(time) <Double-Button>    break
  148.     bind $itk_component(time) <Triple-Button>    break
  149.     bind $itk_component(time) <2>        break
  150.  
  151.     #
  152.     # Initialize the widget based on the command line options.
  153.     #
  154.     eval itk_initialize $args
  155.  
  156.     #
  157.     # Initialize the time to the current time.
  158.     #
  159.     show
  160. }
  161.  
  162. # ------------------------------------------------------------------
  163. #                             OPTIONS
  164. # ------------------------------------------------------------------
  165.  
  166. # ------------------------------------------------------------------
  167. # OPTION: -childsitepos
  168. #
  169. # Specifies the position of the child site in the widget.  Valid
  170. # locations are n, s, e, and w.
  171. # ------------------------------------------------------------------
  172. configbody iwidgets::Timefield::childsitepos {
  173.     set parent [winfo parent $itk_component(time)]
  174.  
  175.     switch $itk_option(-childsitepos) {
  176.       n {
  177.           grid $itk_component(dfchildsite) -row 0 -column 0 -sticky ew
  178.           grid $itk_component(time) -row 1 -column 0 -sticky nsew
  179.  
  180.           grid rowconfigure $parent 0 -weight 0
  181.           grid rowconfigure $parent 1 -weight 1
  182.           grid columnconfigure $parent 0 -weight 1
  183.           grid columnconfigure $parent 1 -weight 0
  184.       }
  185.       
  186.       e {
  187.           grid $itk_component(dfchildsite) -row 0 -column 1 -sticky ns
  188.           grid $itk_component(time) -row 0 -column 0 -sticky nsew
  189.  
  190.           grid rowconfigure $parent 0 -weight 1
  191.           grid rowconfigure $parent 1 -weight 0
  192.           grid columnconfigure $parent 0 -weight 1
  193.           grid columnconfigure $parent 1 -weight 0
  194.       }
  195.       
  196.       s {
  197.           grid $itk_component(dfchildsite) -row 1 -column 0 -sticky ew
  198.           grid $itk_component(time) -row 0 -column 0 -sticky nsew
  199.  
  200.           grid rowconfigure $parent 0 -weight 1
  201.           grid rowconfigure $parent 1 -weight 0
  202.           grid columnconfigure $parent 0 -weight 1
  203.           grid columnconfigure $parent 1 -weight 0
  204.       }
  205.       
  206.       w {
  207.           grid $itk_component(dfchildsite) -row 0 -column 0 -sticky ns
  208.           grid $itk_component(time) -row 0 -column 1 -sticky nsew
  209.  
  210.           grid rowconfigure $parent 0 -weight 1
  211.           grid rowconfigure $parent 1 -weight 0
  212.           grid columnconfigure $parent 0 -weight 0
  213.           grid columnconfigure $parent 1 -weight 1
  214.       }
  215.       
  216.       default {
  217.           error "bad childsite option\
  218.                 \"$itk_option(-childsitepos)\":\
  219.                 should be n, e, s, or w"
  220.       }
  221.     }
  222. }
  223.  
  224. # ------------------------------------------------------------------
  225. # OPTION: -command
  226. #
  227. # Command invoked upon detection of return key press event.
  228. # ------------------------------------------------------------------
  229. configbody iwidgets::Timefield::command {}
  230.  
  231. # ------------------------------------------------------------------
  232. # OPTION: -iq
  233. #
  234. # Specifies the level of intelligence to be shown in the actions
  235. # taken by the time field during the processing of keypress events.
  236. # Valid settings include high or low.  With a high iq,
  237. # the time prevents the user from typing in an invalid time.  For 
  238. # example, if the current time is 05/31/1997 and the user changes
  239. # the hour to 04, then the minute will be instantly modified for them 
  240. # to be 30.  In addition, leap seconds are fully taken into account.
  241. # A setting of low iq instructs the widget to do no validity checking
  242. # at all during time entry.  With a low iq level, it is assumed that
  243. # the validity will be determined at a later time using the time's
  244. # isvalid command.
  245. # ------------------------------------------------------------------
  246. configbody iwidgets::Timefield::iq {
  247.  
  248.   switch $itk_option(-iq) {
  249.     high - low {
  250.  
  251.     }
  252.     default {
  253.       error "bad iq option \"$itk_option(-iq)\": should be high or low"
  254.     }
  255.   }
  256. }
  257.  
  258. # ------------------------------------------------------------------
  259. # OPTION: -format
  260. #
  261. # Specifies the time format displayed in the entry widget.
  262. # ------------------------------------------------------------------
  263. configbody iwidgets::Timefield::format {
  264.  
  265.   switch $itk_option(-format) {
  266.     civilian {
  267.       set _backward _backwardCivilian
  268.       set _forward _forwardCivilian
  269.       set _fields $_civilianFields
  270.       set _numFields 4
  271.       set _formatString "%r"
  272.       $itk_component(time) config -width 11
  273.     }
  274.     military {
  275.       set _backward _backwardMilitary
  276.       set _forward _forwardMilitary
  277.       set _fields $_militaryFields
  278.       set _numFields 3
  279.       set _formatString "%T"
  280.       $itk_component(time) config -width 8
  281.     }
  282.     default {
  283.       error "bad iq option \"$itk_option(-iq)\":\
  284.              should be civilian or military"
  285.     }
  286.   }
  287.  
  288.   #
  289.   # Update the current contents of the entry field to reflect
  290.   # the configured format.
  291.   #
  292.   show $_timeVar($this)
  293. }
  294.  
  295. # ------------------------------------------------------------------
  296. #                            METHODS
  297. # ------------------------------------------------------------------
  298.  
  299. # ------------------------------------------------------------------
  300. # PUBLIC METHOD: get ?format?
  301. #
  302. # Return the current contents of the timefield in one of two formats
  303. # string or as an integer clock value using the -string and -clicks
  304. # options respectively.  The default is by string.  Reference the 
  305. # clock command for more information on obtaining times and their 
  306. # formats.
  307. # ------------------------------------------------------------------
  308. body iwidgets::Timefield::get {{format "-string"}} {
  309.  
  310.   switch -- $format {
  311.     "-string" {
  312.       return $_timeVar($this)
  313.     }
  314.     "-clicks" {
  315.       return [::clock scan $_timeVar($this)]
  316.     }
  317.     default {
  318.       error "bad format option \"$format\":\
  319.                should be -string or -clicks"
  320.     }
  321.   }
  322. }
  323.  
  324. # ------------------------------------------------------------------
  325. # PUBLIC METHOD: show time
  326. #
  327. # Changes the currently displayed time to be that of the time 
  328. # argument.  The time may be specified either as a string or an
  329. # integer clock value.  Reference the clock command for more 
  330. # information on obtaining times and their formats.
  331. # ------------------------------------------------------------------
  332. body iwidgets::Timefield::show {{time "now"}} {
  333.  
  334.   if {$time == {}} {
  335.     set time "now"
  336.   }
  337.  
  338.   switch -regexp -- $time {
  339.  
  340.     {^now$} {
  341.       set seconds [::clock seconds]
  342.     }
  343.  
  344.     {^[0-9]+$} {
  345.       if { [catch {::clock format $time}] } {
  346.         error "bad time: \"$time\", must be a valid time \
  347.            string, clock clicks value or the keyword now"
  348.       }
  349.       set seconds $time
  350.     }
  351.  
  352.     default {
  353.       if {[catch {set seconds [::clock scan $time]}]} {
  354.         error "bad time: \"$time\", must be a valid time \
  355.            string, clock clicks value or the keyword now"
  356.       }
  357.     }
  358.   }
  359.  
  360.   set _timeVar($this) [::clock format $seconds -format $_formatString]
  361. }
  362.  
  363. # ------------------------------------------------------------------
  364. # PUBLIC METHOD: isvalid
  365. #
  366. # Returns a boolean indication of the validity of the currently
  367. # displayed time value.  For example, 09:59::59 is valid whereas
  368. # 26:59:59 is invalid.
  369. # ------------------------------------------------------------------
  370. body iwidgets::Timefield::isvalid {} {
  371.  
  372.   return [expr ([catch {::clock scan $_timeVar($this)}] == 0)]
  373. }
  374.  
  375. # ------------------------------------------------------------------
  376. # PROTECTED METHOD: _focusIn
  377. #
  378. # This method is bound to the <FocusIn> event.  It resets the 
  379. # insert cursor and field settings to be back to their last known
  380. # positions.
  381. # ------------------------------------------------------------------
  382. body iwidgets::Timefield::_focusIn {} {
  383.   _setField $_cfield
  384. }
  385.  
  386. # ------------------------------------------------------------------
  387. # PROTECTED METHOD: _keyPress 
  388. #
  389. # This method is the workhorse of the class.  It is bound to the
  390. # <KeyPress> event and controls the processing of all key strokes.
  391. # ------------------------------------------------------------------
  392. body iwidgets::Timefield::_keyPress {char sym state} {
  393.  
  394.   #
  395.   #  Determine which field we are in currently.  This is needed
  396.   # since the user may have moved to this position via a mouse
  397.   # selection and so it would not be in the position we last 
  398.   # knew it to be.
  399.   #
  400.   set _cfield [_whichField ]
  401.  
  402.   #
  403.   # Set up a few basic variables we'll be needing throughout the
  404.   # rest of the method such as the position of the insert cursor
  405.   # and the currently displayed minute, hour, and second.
  406.   #
  407.   set inValid 0
  408.   set icursor [$itk_component(time) index insert]
  409.   set lastField [lindex $_fields end]
  410.  
  411.   set prevtime $_timeVar($this)
  412.   regexp {^([0-9])([0-9]):([0-9])([0-9]):([0-9])([0-9]).*$} \
  413.         $_timeVar($this) dummy \
  414.         hour1 hour2 minute1 minute2 second1 second2
  415.   set hour    "$hour1$hour2"
  416.   set minute    "$minute1$minute2"
  417.   set second    "$second1$second2"
  418.  
  419.   #
  420.   # Process numeric keystrokes.  This involes a fair amount of 
  421.   # processing with step one being to check and make sure we
  422.   # aren't attempting to insert more that 6 characters.  If
  423.   # so ring the bell and break.
  424.   #
  425.   if {![catch {expr int($char)}]} {
  426.  
  427.     # If we are currently in the hour field then we process the
  428.     # number entered based on the cursor position.  If we are at
  429.     # at the first position and our iq is low, then accept any 
  430.     # input.  
  431.     #
  432.     # if the current format is military, then
  433.     # validate the hour field which can be [00 - 23]
  434.     #
  435.     switch $_cfield {
  436.       hour {
  437.         if {$itk_option(-iq) == "low"} {
  438.           $itk_component(time) delete $icursor
  439.           $itk_component(time) insert $icursor $char
  440.  
  441.         } elseif {$itk_option(-format) == "military"} {
  442.           if {$icursor == 0}  {
  443.             #
  444.             # if the digit is less than 2, then 
  445.             # the second hour digit is valid for 0-9
  446.             #
  447.             if {$char < 2} {
  448.               $itk_component(time) delete 0 1
  449.               $itk_component(time) insert 0 $char
  450.  
  451.             #
  452.             # if the digit is equal to 2, then 
  453.             # the second hour digit is valid for 0-3
  454.             #
  455.             } elseif {$char == 2} {
  456.               $itk_component(time) delete 0 1
  457.               $itk_component(time) insert 0 $char
  458.  
  459.               if {$hour2 > 3} {
  460.                 $itk_component(time) delete 1 2
  461.                 $itk_component(time) insert 1 "0"
  462.                 $itk_component(time) icursor 1
  463.               }
  464.  
  465.             #
  466.             # if the digit is greater than 2, then 
  467.             # set the first hour digit to 0 and the
  468.             # second hour digit to the value.
  469.             #
  470.             } elseif {$char > 2}  {
  471.               $itk_component(time) delete 0 2
  472.               $itk_component(time) insert 0 "0$char"
  473.               set icursor 1
  474.             } else {
  475.               set inValid 1
  476.             }
  477.  
  478.           #
  479.           # if the insertion cursor is for the second hour digit, then
  480.           # format is military, then it can only be valid if the first
  481.           # hour digit is less than 2 or the new digit is less than 4
  482.           #
  483.           } else {
  484.             if {$hour1 < 2 || $char < 4} {
  485.               $itk_component(time) delete 1 2
  486.               $itk_component(time) insert 1 $char
  487.             } else {
  488.               set inValid 1
  489.             }
  490.           }
  491.  
  492.         #
  493.         # The format is civilian, so we need to
  494.         # validate the hour field which can be [01 - 12]
  495.         #
  496.         } else {
  497.           if {$icursor == 0}  {
  498.             #
  499.             # if the digit is 0, then 
  500.             #   the second hour digit is valid for 1-9
  501.             #   so just insert it.
  502.             #
  503.             if {$char == 0 && $hour2 != 0} {
  504.               $itk_component(time) delete 0 1
  505.               $itk_component(time) insert 0 $char
  506.  
  507.             #
  508.             # if the digit is equal to 1, then 
  509.             #   the second hour digit is valid for 0-2
  510.             #
  511.             } elseif {$char == 1} {
  512.               $itk_component(time) delete 0 1
  513.               $itk_component(time) insert 0 $char
  514.  
  515.               if {$hour2 > 2} {
  516.                 $itk_component(time) delete 1 2
  517.                 $itk_component(time) insert 1 0
  518.                 set icursor 1
  519.               }
  520.  
  521.             #
  522.             # if the digit is greater than 1, then 
  523.             #   set the first hour digit to 0 and the
  524.             #   second hour digit to the value.
  525.             #
  526.             } elseif {$char > 1}  {
  527.               $itk_component(time) delete 0 2
  528.               $itk_component(time) insert 0 "0$char"
  529.               set icursor 1
  530.  
  531.             } else {
  532.               set inValid 1
  533.             }
  534.  
  535.           #
  536.           # The insertion cursor is at the second hour digit, so
  537.           # it can only be valid if the firs thour digit is 0
  538.           # or the new digit is less than or equal to 2
  539.           #
  540.           } else {
  541.             if {$hour1 == 0 || $char <= 2} {
  542.               $itk_component(time) delete 1 2
  543.               $itk_component(time) insert 1 $char
  544.             } else {
  545.               set inValid 1
  546.             }
  547.           }
  548.         }
  549.  
  550.         if {$inValid} {
  551.           bell
  552.         } elseif {$icursor == 1} {
  553.           _setField minute
  554.         }
  555.       }
  556.  
  557.       minute {
  558.         if {$itk_option(-iq) == "low" || $char < 6 || $icursor == 4} {
  559.           $itk_component(time) delete $icursor
  560.           $itk_component(time) insert $icursor $char
  561.         } elseif {$itk_option(-iq) == "high"} {
  562.           if {$char > 5} {
  563.             $itk_component(time) delete 3 5
  564.             $itk_component(time) insert 3 "0$char"
  565.             set icursor 4
  566.           }
  567.         }
  568.  
  569.         if {$icursor == 4} {
  570.           _setField second
  571.         }
  572.       }
  573.  
  574.       second {
  575.         if {$itk_option(-iq) == "low" || $char < 6 || $icursor == 7} {
  576.           $itk_component(time) delete $icursor
  577.           $itk_component(time) insert $icursor $char
  578.  
  579.         } elseif {$itk_option(-iq) == "high"} {
  580.           if {$char > 5} {
  581.             $itk_component(time) delete 6 8
  582.             $itk_component(time) insert 6 "0$char"
  583.             set icursor 7
  584.           }
  585.         }
  586.  
  587.         if {$icursor == 7} {
  588.           _moveField forward
  589.         }
  590.       }
  591.     }
  592.  
  593.     return -code break
  594.   }
  595.  
  596.   #
  597.   # Process the plus and the up arrow keys.  They both yield the same
  598.   # effect, they increment the minute by one.
  599.   #
  600.   switch $sym {
  601.     p - P {
  602.       if {$itk_option(-format) == "civilian"} {
  603.         $itk_component(time) delete 9 10
  604.         $itk_component(time) insert 9 P
  605.         _setField hour
  606.       }
  607.     }
  608.  
  609.     a - A {
  610.       if {$itk_option(-format) == "civilian"} {
  611.         $itk_component(time) delete 9 10
  612.         $itk_component(time) insert 9 A
  613.         _setField hour
  614.       }
  615.     }
  616.  
  617.     plus - Up {
  618.       if {$_cfield == "ampm"} {
  619.         _toggleAmPm
  620.       } else {
  621.         set newclicks [::clock scan "$prevtime 1 $_cfield"]
  622.         set newtime   [::clock format $newclicks -format $_formatString]
  623.         set _timeVar($this) $newtime
  624.       }
  625.       return -code continue
  626.     }
  627.  
  628.     minus - Down {
  629.       #
  630.       # Process the minus and the down arrow keys which decrement the value
  631.       # of the field in which the cursor is currently positioned.
  632.       #
  633.       if {$_cfield == "ampm"} {
  634.         _toggleAmPm
  635.       } else {
  636.         set newclicks [::clock scan "$prevtime 1 $_cfield ago"]
  637.         set newtime   [::clock format $newclicks -format $_formatString]
  638.         set _timeVar($this) $newtime
  639.       }
  640.       return -code continue
  641.     }
  642.  
  643.     Tab {
  644.       #
  645.       # A tab key moves the "hour:minute:second" field forward by one unless
  646.       # the current field is the second.  In that case we'll let tab
  647.       # do what is supposed to and pass the focus onto the next widget.
  648.       #
  649.       if {$state == 0} {
  650.  
  651.         if {($itk_option(-format) == "civilian" && $_cfield == $lastField)} {
  652.           _setField hour
  653.           return -code continue
  654.         }
  655.         _moveField forward
  656.  
  657.       #
  658.       # A ctrl-tab key moves the hour:minute:second field backwards by one 
  659.       # unless the current field is the hour.  In that case we'll let 
  660.       # tab take the focus to a previous widget.
  661.       #
  662.       } elseif {$state == 4} {
  663.         if {$_cfield == "hour"} {
  664.           _setField hour
  665.           return -code continue
  666.         }
  667.         _moveField backward
  668.       }
  669.     }
  670.  
  671.     Right {
  672.       #
  673.       # A right arrow key moves the insert cursor to the right one.
  674.       #
  675.       $_forward
  676.     }
  677.  
  678.     Left - BackSpace - Delete {
  679.       #
  680.       # A left arrow, backspace, or delete key moves the insert cursor 
  681.       # to the left one.  This is what you expect for the left arrow
  682.       # and since the whole widget always operates in overstrike mode,
  683.       # it makes the most sense for backspace and delete to do the same.
  684.       #
  685.       $_backward
  686.     }
  687.  
  688.     Return {
  689.       #
  690.       # A Return key invokes the optionally specified command option.
  691.       #
  692.       uplevel #0 $itk_option(-command)
  693.     }
  694.       
  695.     default {
  696.  
  697.     }
  698.   }
  699.  
  700.   return -code break
  701. }
  702.  
  703. # ------------------------------------------------------------------
  704. # PROTECTED METHOD: _toggleAmPm
  705. #
  706. # Internal method which toggles the displayed time
  707. # between "AM" and "PM" when format is "civilian".
  708. # ------------------------------------------------------------------
  709. body iwidgets::Timefield::_toggleAmPm {} {
  710.   set firstChar  [string index $_timeVar($this) 9]
  711.   $itk_component(time) delete 9 10
  712.   $itk_component(time) insert 9 [expr {($firstChar == "A") ? "P" : "A"}]
  713.   $itk_component(time) icursor 9
  714. }
  715.  
  716. # ------------------------------------------------------------------
  717. # PROTECTED METHOD: _setField field
  718. #
  719. # Adjusts the current field to be that of the argument, setting the
  720. # insert cursor appropriately.
  721. # ------------------------------------------------------------------
  722. body iwidgets::Timefield::_setField {field} {
  723.  
  724.   # Move the position of the cursor to the first character of the
  725.   # field given by the argument:
  726.   #
  727.   # Field   First Character Index
  728.   # -----   ---------------------
  729.   # hour    0
  730.   # minute  3
  731.   # second  6
  732.   # ampm    9
  733.   #
  734.   switch $field {
  735.     hour {
  736.       $itk_component(time) icursor 0
  737.     }
  738.     minute {
  739.       $itk_component(time) icursor 3
  740.     }
  741.     second {
  742.       $itk_component(time) icursor 6
  743.     }
  744.     ampm {
  745.       if {$itk_option(-format) == "military"} {
  746.         error "bad field: \"$field\", must be hour, minute or second"
  747.       }
  748.       $itk_component(time) icursor 9
  749.     }
  750.     default {
  751.       if {$itk_option(-format) == "military"} {
  752.         error "bad field: \"$field\", must be hour, minute or second"
  753.       } else {
  754.         error "bad field: \"$field\", must be hour, minute, second or ampm"
  755.       }
  756.     }
  757.   }
  758.  
  759.   set _cfield $field
  760.  
  761.   return $_cfield
  762. }
  763.  
  764. # ------------------------------------------------------------------
  765. # PROTECTED METHOD: _moveField
  766. #
  767. # Moves the cursor one field forward or backward.
  768. # ------------------------------------------------------------------
  769. body iwidgets::Timefield::_moveField {direction} {
  770.  
  771.   # Since the value "_fields" list variable is always either value:
  772.   #   military => {hour minute second}
  773.   #   civilian => {hour minute second ampm}
  774.   #
  775.   # the index of the previous or next field index can be determined
  776.   # by subtracting or adding 1 to current the index, respectively.
  777.   # 
  778.   set index [lsearch $_fields $_cfield]
  779.   expr {($direction == "forward") ? [incr index] : [incr index -1]}
  780.  
  781.   if {$index == $_numFields} {
  782.     set index 0
  783.   } elseif {$index < 0} {
  784.     set index [expr $_numFields-1]
  785.   }
  786.  
  787.   _setField [lindex $_fields $index]
  788. }
  789.  
  790. # ------------------------------------------------------------------
  791. # PROTECTED METHOD: _whichField
  792. #
  793. # Returns the current field that the cursor is positioned within.
  794. # ------------------------------------------------------------------
  795. body iwidgets::Timefield::_whichField {} {
  796.  
  797.   # Return the current field based on the position of the cursor.
  798.   #
  799.   # Field   Index
  800.   # -----   -----
  801.   # hour    0,1
  802.   # minute  3,4
  803.   # second  6,7
  804.   # ampm    9,10
  805.   #
  806.   set icursor [$itk_component(time) index insert]
  807.   switch $icursor {
  808.     0 - 1 {
  809.       set _cfield hour
  810.     }
  811.     3 - 4 {
  812.       set _cfield minute
  813.     }
  814.     6 - 7 {
  815.       set _cfield second
  816.     }
  817.     9 - 10 {
  818.       set _cfield ampm
  819.     }
  820.   }
  821.  
  822.   return $_cfield
  823. }
  824.  
  825. # ------------------------------------------------------------------
  826. # PROTECTED METHOD: _forwardCivilian
  827. #
  828. # Internal method which moves the cursor forward by one character
  829. # jumping over the slashes and wrapping.
  830. # ------------------------------------------------------------------
  831. body iwidgets::Timefield::_forwardCivilian {} {
  832.  
  833.   #
  834.   # If the insertion cursor is at the second digit
  835.   # of either the hour, minute or second field, then
  836.   # move the cursor to the first digit of the right-most field.
  837.   #
  838.   # else move the insertion cursor right one character
  839.   #
  840.   set icursor [$itk_component(time) index insert]
  841.   switch $icursor {
  842.     1 {
  843.       _setField minute
  844.     }
  845.     4 {
  846.       _setField second
  847.     }
  848.     7 {
  849.       _setField ampm
  850.     }
  851.     9 - 10 {
  852.       _setField hour
  853.     }
  854.     default {
  855.       $itk_component(time) icursor [expr $icursor+1]
  856.     }
  857.   }
  858. }
  859.  
  860. # ------------------------------------------------------------------
  861. # PROTECTED METHOD: _forwardMilitary
  862. #
  863. # Internal method which moves the cursor forward by one character
  864. # jumping over the slashes and wrapping.
  865. # ------------------------------------------------------------------
  866. body iwidgets::Timefield::_forwardMilitary {} {
  867.  
  868.   #
  869.   # If the insertion cursor is at the second digit of either
  870.   # the hour, minute or second field, then move the cursor to
  871.   # the first digit of the right-most field.
  872.   #
  873.   # else move the insertion cursor right one character
  874.   #
  875.   set icursor [$itk_component(time) index insert]
  876.   switch $icursor {
  877.     1 {
  878.       _setField minute
  879.     }
  880.     4 {
  881.       _setField second
  882.     }
  883.     7 {
  884.       _setField hour
  885.     }
  886.     default {
  887.       $itk_component(time) icursor [expr $icursor+1]
  888.     }
  889.   }
  890. }
  891.  
  892. # ------------------------------------------------------------------
  893. # PROTECTED METHOD: _backwardCivilian
  894. #
  895. # Internal method which moves the cursor backward by one character
  896. # jumping over the ":" and wrapping.
  897. # ------------------------------------------------------------------
  898. body iwidgets::Timefield::_backwardCivilian {} {
  899.  
  900.   #
  901.   # If the insertion cursor is at the first character
  902.   # of either the minute or second field or at the ampm
  903.   # field, then move the cursor to the second character
  904.   # of the left-most field.
  905.   #
  906.   # else if the insertion cursor is at the first digit of the
  907.   # hour field, then move the cursor to the first character
  908.   # of the ampm field.
  909.   #
  910.   # else move the insertion cursor left one character
  911.   #
  912.   set icursor [$itk_component(time) index insert]
  913.   switch $icursor {
  914.     9 {
  915.       _setField second
  916.       $itk_component(time) icursor 7
  917.     }
  918.     6 {
  919.       _setField minute
  920.       $itk_component(time) icursor 4
  921.     }
  922.     3 {
  923.       _setField hour
  924.       $itk_component(time) icursor 1
  925.     }
  926.     0 {
  927.       _setField ampm
  928.       $itk_component(time) icursor 9
  929.     }
  930.     default {
  931.       $itk_component(time) icursor [expr $icursor-1]
  932.     }
  933.   }
  934. }
  935.  
  936. # ------------------------------------------------------------------
  937. # PROTECTED METHOD: _backwardMilitary
  938. #
  939. # Internal method which moves the cursor backward by one character
  940. # jumping over the slashes and wrapping.
  941. # ------------------------------------------------------------------
  942. body iwidgets::Timefield::_backwardMilitary {} {
  943.  
  944.   #
  945.   # If the insertion cursor is at the first digit of either
  946.   # the minute or second field, then move the cursor to the
  947.   # second character of the left-most field.
  948.   #
  949.   # else if the insertion cursor is at the first digit of the
  950.   # hour field, then move the cursor to the second digit
  951.   # of the second field.
  952.   #
  953.   # else move the insertion cursor left one character
  954.   #
  955.   set icursor [$itk_component(time) index insert]
  956.   switch $icursor {
  957.     6 {
  958.       _setField minute
  959.       $itk_component(time) icursor 4
  960.     }
  961.     3 {
  962.       _setField hour
  963.       $itk_component(time) icursor 1
  964.     }
  965.     0 {
  966.       _setField second
  967.       $itk_component(time) icursor 7
  968.     }
  969.     default {
  970.       $itk_component(time) icursor [expr $icursor-1]
  971.     }
  972.   }
  973. }
  974.