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 / entryfield.itk < prev    next >
Text File  |  1999-02-24  |  18KB  |  524 lines

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