diff options
Diffstat (limited to 'itcl/iwidgets/generic/regexpfield.itk')
-rw-r--r-- | itcl/iwidgets/generic/regexpfield.itk | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/itcl/iwidgets/generic/regexpfield.itk b/itcl/iwidgets/generic/regexpfield.itk new file mode 100644 index 00000000000..3e899082743 --- /dev/null +++ b/itcl/iwidgets/generic/regexpfield.itk @@ -0,0 +1,455 @@ +# +# Regexpfield +# ---------------------------------------------------------------------- +# Implements a text entry widget which accepts input that matches its +# regular expression, and invalidates input which doesn't. +# +# +# ---------------------------------------------------------------------- +# AUTHOR: John A. Tucker E-mail: jatucker@austin.dsccc.com +# +# ---------------------------------------------------------------------- +# Copyright (c) 1995 DSC Technologies Corporation +# ====================================================================== +# Permission to use, copy, modify, distribute and license this software +# and its documentation for any purpose, and without fee or written +# agreement with DSC, is hereby granted, provided that the above copyright +# notice appears in all copies and that both the copyright notice and +# warranty disclaimer below appear in supporting documentation, and that +# the names of DSC Technologies Corporation or DSC Communications +# Corporation not be used in advertising or publicity pertaining to the +# software without specific, written prior permission. +# +# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON- +# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE +# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, +# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL +# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, +# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. +# ====================================================================== + +# +# Usual options. +# +itk::usual Regexpfield { + keep -background -borderwidth -cursor -foreground -highlightcolor \ + -highlightthickness -insertbackground -insertborderwidth \ + -insertofftime -insertontime -insertwidth -labelfont \ + -selectbackground -selectborderwidth -selectforeground \ + -textbackground -textfont +} + +# ------------------------------------------------------------------ +# ENTRYFIELD +# ------------------------------------------------------------------ +itcl::class iwidgets::Regexpfield { + inherit iwidgets::Labeledwidget + + constructor {args} {} + + itk_option define -childsitepos childSitePos Position e + itk_option define -command command Command {} + itk_option define -fixed fixed Fixed 0 + itk_option define -focuscommand focusCommand Command {} + itk_option define -invalid invalid Command bell + itk_option define -regexp regexp Regexp {.*} + itk_option define -nocase nocase Nocase 0 + + public { + method childsite {} + method get {} + method delete {args} + method icursor {args} + method index {args} + method insert {args} + method scan {args} + method selection {args} + method xview {args} + method clear {} + } + + protected { + method _focusCommand {} + method _keyPress {char sym state} + } + + private { + method _peek {char} + } +} + +# +# Provide a lowercased access method for the Regexpfield class. +# +proc ::iwidgets::regexpfield {pathName args} { + uplevel ::iwidgets::Regexpfield $pathName $args +} + +# ------------------------------------------------------------------ +# CONSTRUCTOR +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::constructor {args} { + component hull configure -borderwidth 0 + + itk_component add entry { + entry $itk_interior.entry + } { + keep -borderwidth -cursor -exportselection \ + -foreground -highlightcolor \ + -highlightthickness -insertbackground -insertborderwidth \ + -insertofftime -insertontime -insertwidth -justify \ + -relief -selectbackground -selectborderwidth \ + -selectforeground -show -state -textvariable -width + + rename -font -textfont textFont Font + rename -highlightbackground -background background Background + rename -background -textbackground textBackground Background + } + + # + # Create the child site widget. + # + itk_component add -protected efchildsite { + frame $itk_interior.efchildsite + } + set itk_interior $itk_component(efchildsite) + + # + # Regexpfield instance bindings. + # + bind $itk_component(entry) <KeyPress> [itcl::code $this _keyPress %A %K %s] + bind $itk_component(entry) <FocusIn> [itcl::code $this _focusCommand] + + # + # Initialize the widget based on the command line options. + # + eval itk_initialize $args +} + +# ------------------------------------------------------------------ +# OPTIONS +# ------------------------------------------------------------------ + +# ------------------------------------------------------------------ +# OPTION: -command +# +# Command associated upon detection of Return key press event +# ------------------------------------------------------------------ +itcl::configbody iwidgets::Regexpfield::command {} + +# ------------------------------------------------------------------ +# OPTION: -focuscommand +# +# Command associated upon detection of focus. +# ------------------------------------------------------------------ +itcl::configbody iwidgets::Regexpfield::focuscommand {} + +# ------------------------------------------------------------------ +# OPTION: -regexp +# +# Specify a regular expression to use in performing validation +# of the content of the entry widget. +# ------------------------------------------------------------------ +itcl::configbody iwidgets::Regexpfield::regexp { +} + +# ------------------------------------------------------------------ +# OPTION: -invalid +# +# Specify a command to executed should the current Regexpfield contents +# be proven invalid. +# ------------------------------------------------------------------ +itcl::configbody iwidgets::Regexpfield::invalid {} + +# ------------------------------------------------------------------ +# OPTION: -fixed +# +# Restrict entry to 0 (unlimited) chars. The value is the maximum +# number of chars the user may type into the field, regardles of +# field width, i.e. the field width may be 20, but the user will +# only be able to type -fixed number of characters into it (or +# unlimited if -fixed = 0). +# ------------------------------------------------------------------ +itcl::configbody iwidgets::Regexpfield::fixed { + if {[regexp {[^0-9]} $itk_option(-fixed)] || \ + ($itk_option(-fixed) < 0)} { + error "bad fixed option \"$itk_option(-fixed)\",\ + should be positive integer" + } +} + +# ------------------------------------------------------------------ +# OPTION: -childsitepos +# +# Specifies the position of the child site in the widget. +# ------------------------------------------------------------------ +itcl::configbody iwidgets::Regexpfield::childsitepos { + set parent [winfo parent $itk_component(entry)] + + switch $itk_option(-childsitepos) { + n { + grid $itk_component(efchildsite) -row 0 -column 0 -sticky ew + grid $itk_component(entry) -row 1 -column 0 -sticky nsew + + grid rowconfigure $parent 0 -weight 0 + grid rowconfigure $parent 1 -weight 1 + grid columnconfigure $parent 0 -weight 1 + grid columnconfigure $parent 1 -weight 0 + } + + e { + grid $itk_component(efchildsite) -row 0 -column 1 -sticky ns + grid $itk_component(entry) -row 0 -column 0 -sticky nsew + + grid rowconfigure $parent 0 -weight 1 + grid rowconfigure $parent 1 -weight 0 + grid columnconfigure $parent 0 -weight 1 + grid columnconfigure $parent 1 -weight 0 + } + + s { + grid $itk_component(efchildsite) -row 1 -column 0 -sticky ew + grid $itk_component(entry) -row 0 -column 0 -sticky nsew + + grid rowconfigure $parent 0 -weight 1 + grid rowconfigure $parent 1 -weight 0 + grid columnconfigure $parent 0 -weight 1 + grid columnconfigure $parent 1 -weight 0 + } + + w { + grid $itk_component(efchildsite) -row 0 -column 0 -sticky ns + grid $itk_component(entry) -row 0 -column 1 -sticky nsew + + grid rowconfigure $parent 0 -weight 1 + grid rowconfigure $parent 1 -weight 0 + grid columnconfigure $parent 0 -weight 0 + grid columnconfigure $parent 1 -weight 1 + } + + default { + error "bad childsite option\ + \"$itk_option(-childsitepos)\":\ + should be n, e, s, or w" + } + } +} +# ------------------------------------------------------------------ +# OPTION: -nocase +# +# Specifies whether or not lowercase characters can match either +# lowercase or uppercase letters in string. +# ------------------------------------------------------------------ +itcl::configbody iwidgets::Regexpfield::nocase { + + switch $itk_option(-nocase) { + 0 - 1 { + + } + + default { + error "bad nocase option \"$itk_option(-nocase)\":\ + should be 0 or 1" + } + } +} + +# ------------------------------------------------------------------ +# METHODS +# ------------------------------------------------------------------ + +# ------------------------------------------------------------------ +# METHOD: childsite +# +# Returns the path name of the child site widget. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::childsite {} { + return $itk_component(efchildsite) +} + +# ------------------------------------------------------------------ +# METHOD: get +# +# Thin wrap of the standard entry widget get method. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::get {} { + return [$itk_component(entry) get] +} + +# ------------------------------------------------------------------ +# METHOD: delete +# +# Thin wrap of the standard entry widget delete method. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::delete {args} { + return [eval $itk_component(entry) delete $args] +} + +# ------------------------------------------------------------------ +# METHOD: icursor +# +# Thin wrap of the standard entry widget icursor method. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::icursor {args} { + return [eval $itk_component(entry) icursor $args] +} + +# ------------------------------------------------------------------ +# METHOD: index +# +# Thin wrap of the standard entry widget index method. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::index {args} { + return [eval $itk_component(entry) index $args] +} + +# ------------------------------------------------------------------ +# METHOD: insert +# +# Thin wrap of the standard entry widget index method. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::insert {args} { + return [eval $itk_component(entry) insert $args] +} + +# ------------------------------------------------------------------ +# METHOD: scan +# +# Thin wrap of the standard entry widget scan method. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::scan {args} { + return [eval $itk_component(entry) scan $args] +} + +# ------------------------------------------------------------------ +# METHOD: selection +# +# Thin wrap of the standard entry widget selection method. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::selection {args} { + return [eval $itk_component(entry) selection $args] +} + +# ------------------------------------------------------------------ +# METHOD: xview +# +# Thin wrap of the standard entry widget xview method. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::xview {args} { + return [eval $itk_component(entry) xview $args] +} + +# ------------------------------------------------------------------ +# METHOD: clear +# +# Delete the current entry contents. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::clear {} { + $itk_component(entry) delete 0 end + icursor 0 +} + +# ------------------------------------------------------------------ +# PRIVATE METHOD: _peek char +# +# The peek procedure returns the value of the Regexpfield with the +# char inserted at the insert position. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::_peek {char} { + set str [get] + + set insertPos [index insert] + set firstPart [string range $str 0 [expr {$insertPos - 1}]] + set lastPart [string range $str $insertPos end] + + append rtnVal $firstPart $char $lastPart + return $rtnVal +} + +# ------------------------------------------------------------------ +# PROTECTED METHOD: _focusCommand +# +# Method bound to focus event which evaluates the current command +# specified in the focuscommand option +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::_focusCommand {} { + uplevel #0 $itk_option(-focuscommand) +} + +# ------------------------------------------------------------------ +# PROTECTED METHOD: _keyPress +# +# Monitor the key press event checking for return keys, fixed width +# specification, and optional validation procedures. +# ------------------------------------------------------------------ +itcl::body iwidgets::Regexpfield::_keyPress {char sym state} { + # + # A Return key invokes the optionally specified command option. + # + if {$sym == "Return"} { + uplevel #0 $itk_option(-command) + return -code break 1 + } + + # + # Tabs, BackSpace, and Delete are passed on for other bindings. + # + if {($sym == "Tab") || ($sym == "BackSpace") || ($sym == "Delete")} { + return -code continue 1 + } + + # + # Character is not printable or the state is greater than one which + # means a modifier was used such as a control, meta key, or control + # or meta key with numlock down. + # + if {($char == "") || \ + ($state == 4) || ($state == 8) || \ + ($state == 36) || ($state == 40)} { + return -code continue 1 + } + + # + # If the fixed length option is not zero, then verify that the + # current length plus one will not exceed the limit. If so then + # invoke the invalid command procedure. + # + if {$itk_option(-fixed) != 0} { + if {[string length [get]] >= $itk_option(-fixed)} { + uplevel #0 $itk_option(-invalid) + return -code break 0 + } + } + + set flags "" + + # + # Get the new value of the Regexpfield with the char inserted at the + # insert position. + # + # If the new value doesn't match up with the pattern stored in the + # -regexp option, then the invalid procedure is called. + # + # If the value of the "-nocase" option is true, then add the + # "-nocase" flag to the list of flags. + # + set newVal [_peek $char] + + if {$itk_option(-nocase)} { + set valid [::regexp -nocase -- $itk_option(-regexp) $newVal] + } else { + set valid [::regexp $itk_option(-regexp) $newVal] + } + + if {!$valid} { + uplevel #0 $itk_option(-invalid) + return -code break 0 + } + + return -code continue 1 +} + |