home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 December / PCWorld_2000-12_cd.bin / Komunikace / Comanche / comanche.exe / lib / iwidgets2.2.0 / scripts / entryfield.itk < prev    next >
Text File  |  1999-02-24  |  18KB  |  511 lines

  1. #
  2. # Entryfield
  3. # ----------------------------------------------------------------------
  4. # Implements an enhanced text entry widget.
  5. #
  6. # ----------------------------------------------------------------------
  7. #   AUTHOR:  Sue Yockey               E-mail: syockey@spd.dsccc.com
  8. #                                             yockey@acm.org
  9. #            Mark L. Ulferts          E-mail: mulferts@spd.dsccc.com
  10. #
  11. #   @(#) $Id: entryfield.itk,v 1.2 1998/08/11 14:41:11 welch Exp $
  12. # ----------------------------------------------------------------------
  13. #            Copyright (c) 1995 DSC Technologies Corporation
  14. # ======================================================================
  15. # Permission to use, copy, modify, distribute and license this software 
  16. # and its documentation for any purpose, and without fee or written 
  17. # agreement with DSC, is hereby granted, provided that the above copyright 
  18. # notice appears in all copies and that both the copyright notice and 
  19. # warranty disclaimer below appear in supporting documentation, and that 
  20. # the names of DSC Technologies Corporation or DSC Communications 
  21. # Corporation not be used in advertising or publicity pertaining to the 
  22. # software without specific, written prior permission.
  23. # DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
  24. # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
  25. # INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
  26. # AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, 
  27. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL 
  28. # DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
  29. # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
  30. # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
  31. # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
  32. # SOFTWARE.
  33. # ======================================================================
  34.  
  35. #
  36. # Default resources.
  37. #
  38. option add *Entryfield.borderWidth 2 widgetDefault
  39. option add *Entryfield.relief sunken widgetDefault
  40. option add *Entryfield.labelMargin 2 widgetDefault
  41.  
  42. #
  43. # Usual options.
  44. #
  45. itk::usual Entryfield {
  46.     keep -background -borderwidth -cursor -foreground -highlightcolor \
  47.      -highlightthickness -insertbackground -insertborderwidth \
  48.      -insertofftime -insertontime -insertwidth -labelfont \
  49.      -selectbackground -selectborderwidth -selectforeground \
  50.      -textbackground -textfont
  51. }
  52.  
  53. # ------------------------------------------------------------------
  54. #                            ENTRYFIELD
  55. # ------------------------------------------------------------------
  56. class iwidgets::Entryfield {
  57.     inherit iwidgets::Labeledwidget 
  58.     
  59.     constructor {args} {}
  60.     itk_option define -command command Command {}
  61.     itk_option define -focuscommand focusCommand Command {}
  62.     itk_option define -validate validate Command {}
  63.     itk_option define -invalid invalid Command {bell}
  64.     itk_option define -fixed fixed Fixed 0
  65.     itk_option define -childsitepos childSitePos Position e
  66.     
  67.     public method childsite {}
  68.     public method get {}
  69.     public method delete {args}
  70.     public method icursor {args}
  71.     public method index {args}
  72.     public method insert {args}
  73.     public method scan {args}
  74.     public method selection {args}
  75.     public method xview {args}
  76.     public method clear {}
  77.  
  78.     proc numeric {char} {}
  79.     proc integer {string} {}
  80.     proc alphabetic {char} {}
  81.     proc alphanumeric {char} {}
  82.     proc hexidecimal {string} {}
  83.     proc real {string} {}
  84.     protected method _focusCommand {}
  85.  
  86.     protected method _keyPress {char sym}
  87.  
  88.     private method _peek {char}
  89. }
  90.  
  91. #
  92. # Provide a lowercased access method for the Entryfield class.
  93. proc ::iwidgets::entryfield {pathName args} {
  94.     uplevel ::iwidgets::Entryfield $pathName $args
  95. }
  96.  
  97. # ------------------------------------------------------------------
  98. #                        CONSTRUCTOR
  99. # ------------------------------------------------------------------
  100. body iwidgets::Entryfield::constructor {args} {
  101.     component hull configure -borderwidth 0
  102.     
  103.     itk_component add entry {
  104.     entry $itk_interior.entry
  105.     } {
  106.     keep -borderwidth -cursor -exportselection \
  107.         -foreground -highlightcolor \
  108.         -highlightthickness -insertbackground -insertborderwidth \
  109.         -insertofftime -insertontime -insertwidth -justify \
  110.         -relief -selectbackground -selectborderwidth \
  111.         -selectforeground -show -state -textvariable -width
  112.     
  113.     rename -font -textfont textFont Font
  114.     rename -highlightbackground -background background Background
  115.     rename -background -textbackground textBackground Background
  116.     }
  117.     pack $itk_component(entry) -fill x -expand yes -side left 
  118.     
  119.     #
  120.     # Create the child site widget.
  121.     #
  122.     itk_component add efchildsite {
  123.     frame $itk_interior.efchildsite
  124.     } {
  125.     keep -background -cursor
  126.     }
  127.     set itk_interior $itk_component(efchildsite)
  128.     
  129.     #
  130.     # Entryfield instance bindings.
  131.     #
  132.     bind $itk_component(entry) <KeyPress> \
  133.         [code $this _keyPress %A %K]
  134.  
  135.     bind $itk_component(entry) <FocusIn> \
  136.         [code $this _focusCommand]
  137.     
  138.     #
  139.     # Explicitly handle configs that may have been ignored earlier.
  140.     #
  141.     eval itk_initialize $args
  142. }
  143.  
  144. # ------------------------------------------------------------------
  145. #                             OPTIONS
  146. # ------------------------------------------------------------------
  147.  
  148. # ------------------------------------------------------------------
  149. # OPTION: -command
  150. #
  151. # Command associated upon detection of Return key press event
  152. # ------------------------------------------------------------------
  153. configbody iwidgets::Entryfield::command {}
  154.  
  155. # ------------------------------------------------------------------
  156. # OPTION: -focuscommand
  157. #
  158. # Command associated upon detection of Return key press event
  159. # ------------------------------------------------------------------
  160. configbody iwidgets::Entryfield::focuscommand {}
  161.  
  162. # ------------------------------------------------------------------
  163. # OPTION: -validate
  164. #
  165. # Specify a command to executed for the validation of Entryfields.
  166. # ------------------------------------------------------------------
  167. configbody iwidgets::Entryfield::validate {
  168.     switch $itk_option(-validate) {
  169.     {} {
  170.         set itk_option(-validate) {}
  171.     }
  172.     numeric {
  173.         set itk_option(-validate) "::iwidgets::Entryfield::numeric %c"
  174.     }
  175.     integer {
  176.         set itk_option(-validate) "::iwidgets::Entryfield::integer %P"
  177.     }
  178.     hexidecimal {
  179.         set itk_option(-validate) "::iwidgets::Entryfield::hexidecimal %P"
  180.     }
  181.     real {
  182.         set itk_option(-validate) "::iwidgets::Entryfield::real %P"
  183.     }
  184.     alphabetic {
  185.         set itk_option(-validate) "::iwidgets::Entryfield::alphabetic %c"
  186.     }
  187.     alphanumeric {
  188.         set itk_option(-validate) "::iwidgets::Entryfield::alphanumeric %c"
  189.     }
  190.     }
  191. }
  192.  
  193. # ------------------------------------------------------------------
  194. # OPTION: -invalid
  195. #
  196. # Specify a command to executed should the current Entryfield contents
  197. # be proven invalid.
  198. # ------------------------------------------------------------------
  199. configbody iwidgets::Entryfield::invalid {}
  200.  
  201. # ------------------------------------------------------------------
  202. # OPTION: -fixed
  203. #
  204. # Restrict entry to 0 (unlimited) chars.  The value is the maximum 
  205. # number of chars the user may type into the field, regardles of 
  206. # field width, i.e. the field width may be 20, but the user will 
  207. # only be able to type -fixed number of characters into it (or 
  208. # unlimited if -fixed = 0).
  209. # ------------------------------------------------------------------
  210. configbody iwidgets::Entryfield::fixed {
  211.     if {[regexp {[^0-9]} $itk_option(-fixed)] || \
  212.         ($itk_option(-fixed) < 0)} {
  213.     error "bad fixed option \"$itk_option(-fixed)\",\
  214.         should be positive integer"
  215.     }
  216. }
  217.  
  218. # ------------------------------------------------------------------
  219. # OPTION: -childsitepos
  220. #
  221. # Specifies the position of the child site in the widget.
  222. # ------------------------------------------------------------------
  223. configbody iwidgets::Entryfield::childsitepos {
  224.     switch $itk_option(-childsitepos) {
  225.     n {
  226.         pack configure $itk_component(efchildsite) -side top 
  227.         pack $itk_component(entry) -fill x -expand yes -side top \
  228.             -after $itk_component(efchildsite) 
  229.     }
  230.     
  231.     e {
  232.         pack configure $itk_component(efchildsite) -side left
  233.         pack $itk_component(entry) -fill x -expand yes -side left \
  234.             -before $itk_component(efchildsite) 
  235.     }
  236.     
  237.     s {
  238.         pack $itk_component(entry) -fill x -expand yes -side top 
  239.         pack configure $itk_component(efchildsite) -side top \
  240.             -after $itk_component(entry) 
  241.     }
  242.     
  243.     w {
  244.         pack configure $itk_component(efchildsite) -side left
  245.         pack $itk_component(entry) -fill x -expand yes -side left \
  246.             -after $itk_component(efchildsite) 
  247.     }
  248.     
  249.     default {
  250.         error "bad childsite option\
  251.             \"$itk_option(-childsitepos)\":\
  252.             should be n, e, s, or w"
  253.     }
  254.     }
  255. }
  256.  
  257. # ------------------------------------------------------------------
  258. #                            METHODS
  259. # ------------------------------------------------------------------
  260.  
  261. # ------------------------------------------------------------------
  262. # METHOD: childsite
  263. #
  264. # Returns the path name of the child site widget.
  265. # ------------------------------------------------------------------
  266. body iwidgets::Entryfield::childsite {} {
  267.     return $itk_component(efchildsite)
  268. }
  269.  
  270. # ------------------------------------------------------------------
  271. # METHOD: get 
  272. #
  273. # Thin wrap of the standard entry widget get method.
  274. # ------------------------------------------------------------------
  275. body iwidgets::Entryfield::get {} {
  276.     return [$itk_component(entry) get]
  277. }
  278.  
  279. # ------------------------------------------------------------------
  280. # METHOD: delete
  281. #
  282. # Thin wrap of the standard entry widget delete method.
  283. # ------------------------------------------------------------------
  284. body iwidgets::Entryfield::delete {args} {
  285.     return [eval $itk_component(entry) delete $args]
  286. }
  287.  
  288. # ------------------------------------------------------------------
  289. # METHOD: icursor 
  290. #
  291. # Thin wrap of the standard entry widget icursor method.
  292. # ------------------------------------------------------------------
  293. body iwidgets::Entryfield::icursor {args} {
  294.     return [eval $itk_component(entry) icursor $args]
  295. }
  296.  
  297. # ------------------------------------------------------------------
  298. # METHOD: index 
  299. #
  300. # Thin wrap of the standard entry widget index method.
  301. # ------------------------------------------------------------------
  302. body iwidgets::Entryfield::index {args} {
  303.     return [eval $itk_component(entry) index $args]
  304. }
  305.  
  306. # ------------------------------------------------------------------
  307. # METHOD: insert 
  308. #
  309. # Thin wrap of the standard entry widget index method.
  310. # ------------------------------------------------------------------
  311. body iwidgets::Entryfield::insert {args} {
  312.     return [eval $itk_component(entry) insert $args]
  313. }
  314.  
  315. # ------------------------------------------------------------------
  316. # METHOD: scan 
  317. #
  318. # Thin wrap of the standard entry widget scan method.
  319. # ------------------------------------------------------------------
  320. body iwidgets::Entryfield::scan {args} {
  321.     return [eval $itk_component(entry) scan $args]
  322. }
  323.  
  324. # ------------------------------------------------------------------
  325. # METHOD: selection
  326. #
  327. # Thin wrap of the standard entry widget selection method.
  328. # ------------------------------------------------------------------
  329. body iwidgets::Entryfield::selection {args} {
  330.     return [eval $itk_component(entry) selection $args]
  331. }
  332.  
  333. # ------------------------------------------------------------------
  334. # METHOD: xview 
  335. #
  336. # Thin wrap of the standard entry widget xview method.
  337. # ------------------------------------------------------------------
  338. body iwidgets::Entryfield::xview {args} {
  339.     return [eval $itk_component(entry) xview $args]
  340. }
  341.  
  342. # ------------------------------------------------------------------
  343. # METHOD: clear 
  344. #
  345. # Delete the current entry contents.
  346. # ------------------------------------------------------------------
  347. body iwidgets::Entryfield::clear {} {
  348.     $itk_component(entry) delete 0 end
  349.     icursor 0
  350. }
  351.  
  352. # ------------------------------------------------------------------
  353. # PROCEDURE: numeric char
  354. #
  355. # The numeric procedure validates character input for a given 
  356. # Entryfield to be numeric and returns the result.
  357. # ------------------------------------------------------------------
  358. body iwidgets::Entryfield::numeric {char} {
  359.     return [regexp {[0-9]} $char]
  360. }
  361.  
  362. # ------------------------------------------------------------------
  363. # PROCEDURE: integer string
  364. #
  365. # The integer procedure validates character input for a given 
  366. # Entryfield to be integer and returns the result.
  367. # ------------------------------------------------------------------
  368. body iwidgets::Entryfield::integer {string} {
  369.     return [regexp {^[-+]?[0-9]*$} $string]
  370. }
  371.  
  372. # ------------------------------------------------------------------
  373. # PROCEDURE: alphabetic char
  374. #
  375. # The alphabetic procedure validates character input for a given 
  376. # Entryfield to be alphabetic and returns the result.
  377. # ------------------------------------------------------------------
  378. body iwidgets::Entryfield::alphabetic {char} {
  379.     return [regexp -nocase {[a-z]} $char]
  380. }
  381.  
  382. # ------------------------------------------------------------------
  383. # PROCEDURE: alphanumeric char
  384. #
  385. # The alphanumeric procedure validates character input for a given 
  386. # Entryfield to be alphanumeric and returns the result.
  387. # ------------------------------------------------------------------
  388. body iwidgets::Entryfield::alphanumeric {char} {
  389.     return [regexp -nocase {[0-9a-z]} $char]
  390. }
  391.  
  392. # ------------------------------------------------------------------
  393. # PROCEDURE: hexadecimal string
  394. #
  395. # The hexidecimal procedure validates character input for a given 
  396. # Entryfield to be hexidecimal and returns the result.
  397. # ------------------------------------------------------------------
  398. body iwidgets::Entryfield::hexidecimal {string} {
  399.     return [regexp {^(0x)?[0-9a-fA-F]*$} $string]
  400. }
  401.  
  402. # ------------------------------------------------------------------
  403. # PROCEDURE: real string
  404. #
  405. # The real procedure validates character input for a given Entryfield
  406. # to be real and returns the result.
  407. # ------------------------------------------------------------------
  408. body iwidgets::Entryfield::real {string} {
  409.     return [regexp {^\-?[0-9]*\.?[0-9]*$} $string]
  410. }
  411.  
  412. # ------------------------------------------------------------------
  413. # PRIVATE METHOD: _peek char
  414. #
  415. # The peek procedure returns the value of the Entryfield with the
  416. # char inserted at the insert position.
  417. # ------------------------------------------------------------------
  418. body iwidgets::Entryfield::_peek {char} {
  419.     set str [get]
  420.  
  421.     set insertPos [index insert] 
  422.     set firstPart [string range $str 0 [expr $insertPos - 1]]
  423.     set lastPart [string range $str $insertPos end]
  424.  
  425.     append rtnVal $firstPart $char $lastPart
  426.     return $rtnVal
  427. }
  428.  
  429. # ------------------------------------------------------------------
  430. # PROTECTED METHOD: _focusCommand
  431. #
  432. # Method bound to focus event which evaluates the current command
  433. # specified in the focuscommand option
  434. # ------------------------------------------------------------------
  435. body iwidgets::Entryfield::_focusCommand {} {
  436.     uplevel #0 $itk_option(-focuscommand)
  437. }
  438.  
  439. # ------------------------------------------------------------------
  440. # PROTECTED METHOD: _keyPress 
  441. #
  442. # Monitor the key press event checking for return keys, fixed width
  443. # specification, and optional validation procedures.
  444. # ------------------------------------------------------------------
  445. body iwidgets::Entryfield::_keyPress {char sym} {
  446.     #
  447.     # A Return key invokes the optionally specified command option.
  448.     #
  449.     if {$sym == "Return"} {
  450.     uplevel #0 $itk_option(-command)
  451.     return -code break
  452.     }
  453.     
  454.     #
  455.     # Tabs, BackSpace, and Delete and unprintable characters
  456.     # are passed on for other bindings.
  457.     #
  458.     if {($sym == "Tab") ||
  459.         ($sym == "BackSpace") ||
  460.         ($sym == "Delete") ||
  461.         ($char == "")} {
  462.     return
  463.     }
  464.     
  465.     #
  466.     # If the fixed length option is not zero, then verify that the
  467.     # current length plus one will not exceed the limit.  If so then
  468.     # invoke the invalid command procedure.
  469.     #
  470.     if {$itk_option(-fixed) != 0} {
  471.     if {[string length [get]] >= $itk_option(-fixed)} {
  472.         uplevel #0 $itk_option(-invalid)
  473.         return -code break
  474.     }
  475.     }
  476.     
  477.     #
  478.     # The validate option may contain a keyword (numeric, alphabetic),
  479.     # the name of a procedure, or nothing.  The numeric and alphabetic
  480.     # keywords engage typical base level checks.  If a command procedure
  481.     # is specified, then invoke it with the object and character passed
  482.     # as arguments.  If the validate procedure returns false, then the 
  483.     # invalid procedure is called.
  484.     #
  485.     if {[string length $itk_option(-validate)] > 0} {
  486.     set cmd $itk_option(-validate)
  487.  
  488.     regsub -all "%W" $cmd $itk_component(hull) cmd
  489.     regsub -all "%P" $cmd [_peek $char] cmd
  490.     regsub -all "%S" $cmd [get] cmd
  491.  
  492.         if {$char == "\\"} {
  493.             regsub -all "%c" $cmd {\\\\} cmd
  494.         } elseif {$char == "&"} {
  495.             regsub -all "%c" $cmd {\&} cmd
  496.         } else {
  497.             regsub "\"|\\\[|\\\]|{|}| " $char {\\\0} char
  498.             regsub -all "%c" $cmd $char cmd
  499.         }
  500.  
  501.     set valid [uplevel #0 $cmd]
  502.  
  503.     if {($valid == "") || (! $valid)} {
  504.         uplevel #0 $itk_option(-invalid)
  505.         return -code break
  506.     }
  507.     }
  508. }
  509.