1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
#!/usr/bin/env wish
#==============================================================================
# Demonstrates how to implement a multi-entry widget for 10-digit phone numbers.
#
# Copyright (c) 1999-2018 Csaba Nemethi (E-mail: csaba.nemethi@t-online.de)
#==============================================================================
package require mentry_tile
set title "Phone Number"
wm title . $title
#
# Add some entries to the Tk option database
#
source [file join [file dirname [info script]] option_tile.tcl]
#------------------------------------------------------------------------------
# phoneNumberMentry
#
# Creates a new mentry widget win that allows to display and edit 10-digit
# phone numbers. Sets the type attribute of the widget to PhoneNumber and
# returns the name of the newly created widget.
#------------------------------------------------------------------------------
proc phoneNumberMentry {win args} {
#
# Create a mentry widget consisting of two entries of width 3 and one of
# width 4, separated by "-" characters, and set its type to PhoneNumber
#
eval [list mentry::mentry $win] $args
$win configure -body {3 - 3 - 4}
$win attrib type PhoneNumber
#
# Allow only decimal digits in all entry children; use
# wcb::cbappend (or wcb::cbprepend) instead of wcb::callback
# in order to keep the wcb::checkEntryLen callback,
# registered by mentry::mentry for all entry children
#
for {set n 0} {$n < 3} {incr n} {
$win adjustentry $n "0123456789"
wcb::cbappend [$win entrypath $n] before insert wcb::checkStrForNum
}
return $win
}
#------------------------------------------------------------------------------
# putPhoneNumber
#
# Outputs the phone number num to the mentry widget win of type PhoneNumber.
# The phone number must be a string of length 10, consisting of decimal digits.
#------------------------------------------------------------------------------
proc putPhoneNumber {num win} {
#
# Check the syntax of num
#
if {[string length $num] != 10 || ![regexp {^[0-9]*$} $num]} {
return -code error "expected 10 decimal digits but got \"$num\""
}
#
# Check the widget and display the properly formatted phone number
#
checkIfPhoneNumberMentry $win
$win put 0 [string range $num 0 2] [string range $num 3 5] \
[string range $num 6 9]
}
#------------------------------------------------------------------------------
# getPhoneNumber
#
# Returns the phone number contained in the mentry widget win of type
# PhoneNumber.
#------------------------------------------------------------------------------
proc getPhoneNumber win {
#
# Check the widget
#
checkIfPhoneNumberMentry $win
#
# Generate an error if any entry child is empty or incomplete
#
for {set n 0} {$n < 3} {incr n} {
if {[$win isempty $n]} {
focus [$win entrypath $n]
return -code error EMPTY
}
if {![$win isfull $n]} {
focus [$win entrypath $n]
return -code error INCOMPL
}
}
#
# Return the phone number built from the
# values contained in the entry children
#
$win getarray strs
return $strs(0)$strs(1)$strs(2)
}
#------------------------------------------------------------------------------
# checkIfPhoneNumberMentry
#
# Generates an error if win is not a mentry widget of type PhoneNumber.
#------------------------------------------------------------------------------
proc checkIfPhoneNumberMentry win {
if {![winfo exists $win]} {
return -code error "bad window path name \"$win\""
}
if {[string compare [winfo class $win] "Mentry"] != 0 ||
[string compare [$win attrib type] "PhoneNumber"] != 0} {
return -code error \
"window \"$win\" is not a mentry widget for phone numbers"
}
}
#------------------------------------------------------------------------------
#
# Improve the window's appearance by using a tile
# frame as a container for the other widgets
#
ttk::frame .base
#
# Frame .base.f with a mentry displaying a phone number
#
ttk::frame .base.f
ttk::label .base.f.l -text "A mentry widget for phone numbers:"
phoneNumberMentry .base.f.me
pack .base.f.l .base.f.me
#
# Message strings corresponding to the values
# returned by getPhoneNumber on failure
#
array set msgs {
EMPTY "Field value missing"
INCOMPL "Incomplete field value"
}
#
# Button .base.get invoking the procedure getPhoneNumber
#
ttk::button .base.get -text "Get from mentry" -command {
if {[catch {
set num ""
set num [getPhoneNumber .base.f.me]
} result] != 0} {
bell
tk_messageBox -icon error -message $msgs($result) \
-title $title -type ok
}
}
#
# Label .base.num displaying the result of getPhoneNumber
#
ttk::label .base.num -textvariable num -background white
#
# Separator .base.sep and button .base.close
#
ttk::separator .base.sep -orient horizontal
ttk::button .base.close -text Close -command exit
#
# Manage the widgets
#
pack .base.close -side bottom -pady 10
pack .base.sep -side bottom -fill x
pack .base.f -padx 10 -pady 10
pack .base.get -padx 10
pack .base.num -padx 10 -pady 10
pack .base -expand yes -fill both
putPhoneNumber 1234567890 .base.f.me
focus [.base.f.me entrypath 0]
|