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 / regexpfield.itk < prev    next >
Text File  |  1999-02-24  |  15KB  |  456 lines

  1. #
  2. # Regexpfield
  3. # ----------------------------------------------------------------------
  4. # Implements a text entry widget which accepts input that matches its
  5. # regular expression, and invalidates input which doesn't.
  6. #
  7. # ----------------------------------------------------------------------
  8. #   AUTHOR:  John A. Tucker           E-mail: jatucker@austin.dsccc.com
  9. #
  10. # ----------------------------------------------------------------------
  11. #            Copyright (c) 1995 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. # Usual options.
  35. #
  36. itk::usual Regexpfield {
  37.     keep -background -borderwidth -cursor -foreground -highlightcolor \
  38.      -highlightthickness -insertbackground -insertborderwidth \
  39.      -insertofftime -insertontime -insertwidth -labelfont \
  40.      -selectbackground -selectborderwidth -selectforeground \
  41.      -textbackground -textfont
  42. }
  43.  
  44. # ------------------------------------------------------------------
  45. #                            ENTRYFIELD
  46. # ------------------------------------------------------------------
  47. class iwidgets::Regexpfield {
  48.     inherit iwidgets::Labeledwidget 
  49.     
  50.     constructor {args} {}
  51.  
  52.     itk_option define -childsitepos childSitePos Position e
  53.     itk_option define -command command Command {}
  54.     itk_option define -fixed fixed Fixed 0
  55.     itk_option define -focuscommand focusCommand Command {}
  56.     itk_option define -invalid invalid Command bell
  57.     itk_option define -regexp regexp Regexp {.*}
  58.     itk_option define -nocase nocase Nocase 0
  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.     protected {
  74.     method _focusCommand {}
  75.     method _keyPress {char sym state}
  76.     }
  77.  
  78.     private {
  79.     method _peek {char}
  80.     }
  81. }
  82.  
  83. #
  84. # Provide a lowercased access method for the Regexpfield class.
  85. proc ::iwidgets::regexpfield {pathName args} {
  86.     uplevel ::iwidgets::Regexpfield $pathName $args
  87. }
  88.  
  89. # ------------------------------------------------------------------
  90. #                        CONSTRUCTOR
  91. # ------------------------------------------------------------------
  92. body iwidgets::Regexpfield::constructor {args} {
  93.     component hull configure -borderwidth 0
  94.     
  95.     itk_component add entry {
  96.     entry $itk_interior.entry
  97.     } {
  98.     keep -borderwidth -cursor -exportselection \
  99.         -foreground -highlightcolor \
  100.         -highlightthickness -insertbackground -insertborderwidth \
  101.         -insertofftime -insertontime -insertwidth -justify \
  102.         -relief -selectbackground -selectborderwidth \
  103.         -selectforeground -show -state -textvariable -width
  104.     
  105.     rename -font -textfont textFont Font
  106.     rename -highlightbackground -background background Background
  107.     rename -background -textbackground textBackground Background
  108.     }
  109.     
  110.     #
  111.     # Create the child site widget.
  112.     #
  113.     itk_component add -protected efchildsite {
  114.     frame $itk_interior.efchildsite
  115.     } 
  116.     set itk_interior $itk_component(efchildsite)
  117.     
  118.     #
  119.     # Regexpfield instance bindings.
  120.     #
  121.     bind $itk_component(entry) <KeyPress> [code $this _keyPress %A %K %s]
  122.     bind $itk_component(entry) <FocusIn> [code $this _focusCommand]
  123.     
  124.     #
  125.     # Initialize the widget based on the command line options.
  126.     #
  127.     eval itk_initialize $args
  128. }
  129.  
  130. # ------------------------------------------------------------------
  131. #                             OPTIONS
  132. # ------------------------------------------------------------------
  133.  
  134. # ------------------------------------------------------------------
  135. # OPTION: -command
  136. #
  137. # Command associated upon detection of Return key press event
  138. # ------------------------------------------------------------------
  139. configbody iwidgets::Regexpfield::command {}
  140.  
  141. # ------------------------------------------------------------------
  142. # OPTION: -focuscommand
  143. #
  144. # Command associated upon detection of focus.
  145. # ------------------------------------------------------------------
  146. configbody iwidgets::Regexpfield::focuscommand {}
  147.  
  148. # ------------------------------------------------------------------
  149. # OPTION: -regexp
  150. #
  151. # Specify a regular expression to use in performing validation
  152. # of the content of the entry widget.
  153. # ------------------------------------------------------------------
  154. configbody iwidgets::Regexpfield::regexp {
  155. }
  156.  
  157. # ------------------------------------------------------------------
  158. # OPTION: -invalid
  159. #
  160. # Specify a command to executed should the current Regexpfield contents
  161. # be proven invalid.
  162. # ------------------------------------------------------------------
  163. configbody iwidgets::Regexpfield::invalid {}
  164.  
  165. # ------------------------------------------------------------------
  166. # OPTION: -fixed
  167. #
  168. # Restrict entry to 0 (unlimited) chars.  The value is the maximum 
  169. # number of chars the user may type into the field, regardles of 
  170. # field width, i.e. the field width may be 20, but the user will 
  171. # only be able to type -fixed number of characters into it (or 
  172. # unlimited if -fixed = 0).
  173. # ------------------------------------------------------------------
  174. configbody iwidgets::Regexpfield::fixed {
  175.     if {[regexp {[^0-9]} $itk_option(-fixed)] || \
  176.         ($itk_option(-fixed) < 0)} {
  177.     error "bad fixed option \"$itk_option(-fixed)\",\
  178.         should be positive integer"
  179.     }
  180. }
  181.  
  182. # ------------------------------------------------------------------
  183. # OPTION: -childsitepos
  184. #
  185. # Specifies the position of the child site in the widget.
  186. # ------------------------------------------------------------------
  187. configbody iwidgets::Regexpfield::childsitepos {
  188.     set parent [winfo parent $itk_component(entry)]
  189.  
  190.     switch $itk_option(-childsitepos) {
  191.     n {
  192.         grid $itk_component(efchildsite) -row 0 -column 0 -sticky ew
  193.         grid $itk_component(entry) -row 1 -column 0 -sticky nsew
  194.  
  195.         grid rowconfigure $parent 0 -weight 0
  196.         grid rowconfigure $parent 1 -weight 1
  197.         grid columnconfigure $parent 0 -weight 1
  198.         grid columnconfigure $parent 1 -weight 0
  199.     }
  200.     
  201.     e {
  202.         grid $itk_component(efchildsite) -row 0 -column 1 -sticky ns
  203.         grid $itk_component(entry) -row 0 -column 0 -sticky nsew
  204.  
  205.         grid rowconfigure $parent 0 -weight 1
  206.         grid rowconfigure $parent 1 -weight 0
  207.         grid columnconfigure $parent 0 -weight 1
  208.         grid columnconfigure $parent 1 -weight 0
  209.     }
  210.     
  211.     s {
  212.         grid $itk_component(efchildsite) -row 1 -column 0 -sticky ew
  213.         grid $itk_component(entry) -row 0 -column 0 -sticky nsew
  214.  
  215.         grid rowconfigure $parent 0 -weight 1
  216.         grid rowconfigure $parent 1 -weight 0
  217.         grid columnconfigure $parent 0 -weight 1
  218.         grid columnconfigure $parent 1 -weight 0
  219.     }
  220.     
  221.     w {
  222.         grid $itk_component(efchildsite) -row 0 -column 0 -sticky ns
  223.         grid $itk_component(entry) -row 0 -column 1 -sticky nsew
  224.  
  225.         grid rowconfigure $parent 0 -weight 1
  226.         grid rowconfigure $parent 1 -weight 0
  227.         grid columnconfigure $parent 0 -weight 0
  228.         grid columnconfigure $parent 1 -weight 1
  229.     }
  230.     
  231.     default {
  232.         error "bad childsite option\
  233.             \"$itk_option(-childsitepos)\":\
  234.             should be n, e, s, or w"
  235.     }
  236.     }
  237. }
  238. # ------------------------------------------------------------------
  239. # OPTION: -nocase
  240. #
  241. # Specifies whether or not lowercase characters can match either
  242. # lowercase or uppercase letters in string.
  243. # ------------------------------------------------------------------
  244. configbody iwidgets::Regexpfield::nocase {
  245.  
  246.     switch $itk_option(-nocase) {
  247.     0 - 1 {
  248.  
  249.     }
  250.     
  251.     default {
  252.         error "bad nocase option \"$itk_option(-nocase)\":\
  253.             should be 0 or 1"
  254.     }
  255.     }
  256. }
  257.  
  258. # ------------------------------------------------------------------
  259. #                            METHODS
  260. # ------------------------------------------------------------------
  261.  
  262. # ------------------------------------------------------------------
  263. # METHOD: childsite
  264. #
  265. # Returns the path name of the child site widget.
  266. # ------------------------------------------------------------------
  267. body iwidgets::Regexpfield::childsite {} {
  268.     return $itk_component(efchildsite)
  269. }
  270.  
  271. # ------------------------------------------------------------------
  272. # METHOD: get 
  273. #
  274. # Thin wrap of the standard entry widget get method.
  275. # ------------------------------------------------------------------
  276. body iwidgets::Regexpfield::get {} {
  277.     return [$itk_component(entry) get]
  278. }
  279.  
  280. # ------------------------------------------------------------------
  281. # METHOD: delete
  282. #
  283. # Thin wrap of the standard entry widget delete method.
  284. # ------------------------------------------------------------------
  285. body iwidgets::Regexpfield::delete {args} {
  286.     return [eval $itk_component(entry) delete $args]
  287. }
  288.  
  289. # ------------------------------------------------------------------
  290. # METHOD: icursor 
  291. #
  292. # Thin wrap of the standard entry widget icursor method.
  293. # ------------------------------------------------------------------
  294. body iwidgets::Regexpfield::icursor {args} {
  295.     return [eval $itk_component(entry) icursor $args]
  296. }
  297.  
  298. # ------------------------------------------------------------------
  299. # METHOD: index 
  300. #
  301. # Thin wrap of the standard entry widget index method.
  302. # ------------------------------------------------------------------
  303. body iwidgets::Regexpfield::index {args} {
  304.     return [eval $itk_component(entry) index $args]
  305. }
  306.  
  307. # ------------------------------------------------------------------
  308. # METHOD: insert 
  309. #
  310. # Thin wrap of the standard entry widget index method.
  311. # ------------------------------------------------------------------
  312. body iwidgets::Regexpfield::insert {args} {
  313.     return [eval $itk_component(entry) insert $args]
  314. }
  315.  
  316. # ------------------------------------------------------------------
  317. # METHOD: scan 
  318. #
  319. # Thin wrap of the standard entry widget scan method.
  320. # ------------------------------------------------------------------
  321. body iwidgets::Regexpfield::scan {args} {
  322.     return [eval $itk_component(entry) scan $args]
  323. }
  324.  
  325. # ------------------------------------------------------------------
  326. # METHOD: selection
  327. #
  328. # Thin wrap of the standard entry widget selection method.
  329. # ------------------------------------------------------------------
  330. body iwidgets::Regexpfield::selection {args} {
  331.     return [eval $itk_component(entry) selection $args]
  332. }
  333.  
  334. # ------------------------------------------------------------------
  335. # METHOD: xview 
  336. #
  337. # Thin wrap of the standard entry widget xview method.
  338. # ------------------------------------------------------------------
  339. body iwidgets::Regexpfield::xview {args} {
  340.     return [eval $itk_component(entry) xview $args]
  341. }
  342.  
  343. # ------------------------------------------------------------------
  344. # METHOD: clear 
  345. #
  346. # Delete the current entry contents.
  347. # ------------------------------------------------------------------
  348. body iwidgets::Regexpfield::clear {} {
  349.     $itk_component(entry) delete 0 end
  350.     icursor 0
  351. }
  352.  
  353. # ------------------------------------------------------------------
  354. # PRIVATE METHOD: _peek char
  355. #
  356. # The peek procedure returns the value of the Regexpfield with the
  357. # char inserted at the insert position.
  358. # ------------------------------------------------------------------
  359. body iwidgets::Regexpfield::_peek {char} {
  360.     set str [get]
  361.  
  362.     set insertPos [index insert] 
  363.     set firstPart [string range $str 0 [expr $insertPos - 1]]
  364.     set lastPart [string range $str $insertPos end]
  365.  
  366.     append rtnVal $firstPart $char $lastPart
  367.     return $rtnVal
  368. }
  369.  
  370. # ------------------------------------------------------------------
  371. # PROTECTED METHOD: _focusCommand
  372. #
  373. # Method bound to focus event which evaluates the current command
  374. # specified in the focuscommand option
  375. # ------------------------------------------------------------------
  376. body iwidgets::Regexpfield::_focusCommand {} {
  377.     uplevel #0 $itk_option(-focuscommand)
  378. }
  379.  
  380. # ------------------------------------------------------------------
  381. # PROTECTED METHOD: _keyPress 
  382. #
  383. # Monitor the key press event checking for return keys, fixed width
  384. # specification, and optional validation procedures.
  385. # ------------------------------------------------------------------
  386. body iwidgets::Regexpfield::_keyPress {char sym state} {
  387.     #
  388.     # A Return key invokes the optionally specified command option.
  389.     #
  390.     if {$sym == "Return"} {
  391.     uplevel #0 $itk_option(-command)
  392.     return -code break 1
  393.     } 
  394.     
  395.     #
  396.     # Tabs, BackSpace, and Delete are passed on for other bindings.
  397.     #
  398.     if {($sym == "Tab") || ($sym == "BackSpace") || ($sym == "Delete")} {
  399.     return -code continue 1
  400.     }
  401.     
  402.     # 
  403.     # Character is not printable or the state is greater than one which
  404.     # means a modifier was used such as a control, meta key, or control
  405.     # or meta key with numlock down.
  406.     #
  407.     if {($char == "") || \
  408.         ($state == 4) || ($state == 8) || \
  409.         ($state == 36) || ($state == 40)} {
  410.     return -code continue 1
  411.     }
  412.  
  413.     #
  414.     # If the fixed length option is not zero, then verify that the
  415.     # current length plus one will not exceed the limit.  If so then
  416.     # invoke the invalid command procedure.
  417.     #
  418.     if {$itk_option(-fixed) != 0} {
  419.     if {[string length [get]] >= $itk_option(-fixed)} {
  420.         uplevel #0 $itk_option(-invalid)
  421.         return -code break 0
  422.     }
  423.     } 
  424.  
  425.     set flags ""
  426.  
  427.     #
  428.     # Get the new value of the Regexpfield with the char inserted at the
  429.     # insert position.
  430.     #
  431.     # If the new value doesn't match up with the pattern stored in the
  432.     # -regexp option, then the invalid procedure is called.
  433.     #
  434.     # If the value of the "-nocase" option is true, then add the
  435.     # "-nocase" flag to the list of flags.
  436.     #
  437.     set newVal [_peek $char]
  438.  
  439.     if {$itk_option(-nocase)} {
  440.     set valid [::regexp -nocase -- $itk_option(-regexp) $newVal]
  441.     } else {
  442.     set valid [::regexp $itk_option(-regexp) $newVal]
  443.     }
  444.  
  445.     if {!$valid} {
  446.     uplevel #0 $itk_option(-invalid)
  447.     return -code break 0
  448.     }
  449.  
  450.     return -code continue 1
  451. }
  452.  
  453.