865 lines
31 KiB
HTML
865 lines
31 KiB
HTML
<html>
|
|
<head>
|
|
<title>Mentry Programmer's Guide</title>
|
|
|
|
<meta name="Author" content="Csaba Nemethi">
|
|
<meta name="Keywords" content="mentry, widget, entry, label">
|
|
|
|
<style type="text/css">
|
|
<!--
|
|
pre {color: #006400}
|
|
-->
|
|
</style>
|
|
</head>
|
|
|
|
<body bgcolor=#ffffff>
|
|
<div align=center>
|
|
<h1>Mentry Programmer's Guide</h1>
|
|
|
|
<h3>by</h3>
|
|
|
|
<h2>Csaba Nemethi</h2>
|
|
|
|
<address>
|
|
<a href="mailto:csaba.nemethi@t-online.de">csaba.nemethi@t-online.de</a>
|
|
</address>
|
|
</div>
|
|
|
|
|
|
<p><hr>
|
|
|
|
|
|
<h2><a name="contents"></a>Contents</h2>
|
|
|
|
|
|
<h4><a href="#overview">Overview</a></h4>
|
|
|
|
<ul>
|
|
<li><a href="#ov_what">What is Mentry?</a>
|
|
<li><a href="#ov_get">How to get it?</a>
|
|
<li><a href="#ov_install">How to install it?</a>
|
|
<li><a href="#ov_use">How to use it?</a>
|
|
</ul>
|
|
|
|
<h4><a href="#examples">Examples</a></h4>
|
|
|
|
<ul>
|
|
<li><a href="#ex_phoneNumber">A mentry widget for phone numbers</a>
|
|
<li><a href="#ex_ethernetAddr">A mentry widget for Ethernet addresses</a>
|
|
<li><a href="#ex_dateTime">Using mentry widgets for date and time</a>
|
|
</ul>
|
|
|
|
<div align=center>
|
|
<p><a href="index.html">Start page</a>
|
|
</div>
|
|
|
|
|
|
<p><hr>
|
|
|
|
|
|
<h2><a name="overview"></a>Overview</h2>
|
|
|
|
|
|
<h3><a name="ov_what"></a>What is Mentry?</h3>
|
|
|
|
<p>Mentry is a library package for Tcl/Tk version 8.0 or higher, written in
|
|
pure Tcl/Tk code. It contains:
|
|
|
|
<ul>
|
|
<li>the implementation of the <a href="mentryWidget.html">multi-entry
|
|
mega-widget <b>mentry</b></a>, including a general utility module for
|
|
mega-widgets;
|
|
<li>procedures that facilitate the use of multi-entry widgets for displaying
|
|
and editing <a href="mentryDateTime.html">date and time</a> in a great
|
|
variety of formats, <a href="mentryFixedPoint.html">real numbers in
|
|
fixed-point format</a>, as well as <a href="mentryIPAddr.html">IP
|
|
addresses</a>;
|
|
<li>two richly commented demo scripts containing the typical steps needed to
|
|
create and handle a mentry widget for a particular purpose;
|
|
<li>a demo script that shows how to use the date- and time-related
|
|
procedures;
|
|
<li>this tutorial;
|
|
<li>reference pages in HTML format.
|
|
</ul>
|
|
|
|
<p>A multi-entry widget consists of any number of entry widgets separated by
|
|
labels, all embedded in a frame. Appropriately chosen configuration
|
|
options make this conglomerate look like one single entry containing
|
|
preinserted text pieces having invariant positions within the widget.
|
|
The initial width of an entry child also determines the maximal number of
|
|
characters that can be inserted into it; when reaching this limit in an entry
|
|
having the input focus, the latter is set automatically to the next enabled
|
|
entry child. The same action is triggered by typing a character contained
|
|
in the label following the current entry, if the latter is non-empty.
|
|
|
|
<p>Within a mentry widget, the <code>Left</code>, <code>Right</code>,
|
|
<code>Home</code>, <code>End</code>, and <code>BackSpace</code> keys work
|
|
across entry boundaries, while <code>Control-Left</code> and
|
|
<code>Control-Right</code> play the same role as <code>Tab</code> and
|
|
<code>Shift-Tab</code> in the case of ordinary entries.
|
|
|
|
<p>Some of the above features are implemented with the aid of the widget
|
|
callback package Wcb, written in pure Tcl/Tk code as well.
|
|
<b>The Mentry package requires version 2.7 or higher of Wcb</b>, whose download
|
|
location is
|
|
|
|
<blockquote><address>
|
|
<a href="http://www.nemethi.de">http://www.nemethi.de</a>
|
|
</address></blockquote>
|
|
|
|
<a name="ov_example"></a>
|
|
<p>It is very easy to create a multi-entry widget. For example, the
|
|
command
|
|
|
|
<blockquote><pre>
|
|
mentry::mentry .me -body {3 - 3 - 4}
|
|
</pre></blockquote>
|
|
|
|
<p>will create a mentry widget consisting of two entries of width 3 and one of
|
|
width 4, separated by <code>"-"</code> characters. With the command
|
|
|
|
<blockquote><pre>
|
|
foreach w [.me entries] {
|
|
wcb::cbappend $w before insert wcb::checkStrForNum
|
|
}
|
|
</pre></blockquote>
|
|
|
|
<p>you can make sure that the three entries will only accept numeric input,
|
|
thus providing a comfortable and safe user interface for editing 10-digit
|
|
phone numbers.
|
|
|
|
|
|
<h3><a name="ov_get"></a>How to get it?</h3>
|
|
|
|
<p>Mentry is available for free download from the same URL as Wcb. The
|
|
distribution file is <code>mentry2.8.tar.gz</code> for UNIX and
|
|
<code>mentry2_8.zip</code> for Windows. These files contain the same
|
|
information, except for the additional carriage return character preceding the
|
|
linefeed at the end of each line in the text files for Windows.
|
|
|
|
|
|
<h3><a name="ov_install"></a>How to install it?</h3>
|
|
|
|
<p>Install the package as a subdirectory of one of the directories given by the
|
|
<code>auto_path</code> variable. For example, you can install it as a
|
|
directory at the same level as the Tcl and Tk script libraries. The
|
|
locations of these library directories are given by the
|
|
<code>tcl_library</code> and <code>tk_library</code> variables, respectively.
|
|
|
|
<p>To install Mentry <i>on UNIX</i>, <code>cd</code> to the desired directory
|
|
and unpack the distribution file <code>mentry2.8.tar.gz</code>:
|
|
|
|
<blockquote><pre>
|
|
gunzip -c mentry2.8.tar.gz | tar -xf -
|
|
</pre></blockquote>
|
|
|
|
<p>This command will create a directory named <code>mentry2.8</code>, with the
|
|
subdirectories <code>demos</code>, <code>doc</code>, and <code>scripts</code>.
|
|
|
|
<p><i>On Windows</i>, use WinZip or some other program capable of unpacking the
|
|
distribution file <code>mentry2_8.zip</code> into the directory
|
|
<code>mentry2.8</code>, with the subdirectories <code>demos</code>,
|
|
<code>doc</code>, and <code>scripts</code>.
|
|
|
|
|
|
<h3><a name="ov_use"></a>How to use it?</h3>
|
|
|
|
<p>To be able to access the commands and variables defined in the package
|
|
Mentry, your scripts must contain one of the lines
|
|
|
|
<blockquote><pre>
|
|
package require Mentry
|
|
package require mentry
|
|
</pre></blockquote>
|
|
|
|
<p>You can use either one of the above two statements because the file
|
|
<code>mentry.tcl</code> contains both lines
|
|
|
|
<blockquote><pre>
|
|
package provide Mentry ...
|
|
package provide mentry ...
|
|
</pre></blockquote>
|
|
|
|
<p>You are free to remove one of these two lines from <code>mentry.tcl</code>
|
|
if you want to prevent the package from making itself known under two different
|
|
names. Of course, by doing so you restrict the argument of
|
|
<code>package require</code> to a single name. Notice that the
|
|
<a href="#examples">examples</a> below use the statement <code>package
|
|
require Mentry</code>.
|
|
|
|
<p>Since the package Mentry is implemented in its own namespace called
|
|
<code>mentry</code>, you must either invoke the
|
|
|
|
<blockquote><pre>
|
|
namespace import mentry::<i>pattern</i> ?mentry::<i>pattern ...</i>?
|
|
</pre></blockquote>
|
|
|
|
<p>command to import the <i>procedures</i> you need, or use qualified names
|
|
like <code>mentry::mentry</code>. In the examples below we have chosen
|
|
the latter approach.
|
|
|
|
<p>To access Mentry <i>variables</i>, you <i>must</i> use qualified
|
|
names. There are only two Mentry variables that are designed to be
|
|
accessed outside the namespace <code>mentry</code>:
|
|
|
|
<ul>
|
|
<li>The variable <code>mentry::version</code> holds the current version
|
|
number of the Mentry package.
|
|
<li>The variable <code>mentry::library</code> holds the location of the
|
|
Mentry installation directory.
|
|
</ul>
|
|
|
|
<div align=center>
|
|
<p><a href="#contents">Contents</a>
|
|
<a href="index.html">Start page</a>
|
|
</div>
|
|
|
|
|
|
<p><hr>
|
|
|
|
|
|
<h2><a name="examples"></a>Examples</h2>
|
|
|
|
|
|
<h3><a name="ex_phoneNumber"></a>A mentry widget for phone numbers</h3>
|
|
|
|
<p>Let's resume the <a href="#ov_example">example</a> mentioned in the Overview
|
|
in a bit more systematical manner. First, we will write a procedure for
|
|
creating a mentry widget that allows to display and edit 10-digit phone numbers
|
|
and accepts any configuration options supported by the <code><a href=
|
|
"mentryWidget.html">mentry::mentry</a></code> command:
|
|
|
|
<blockquote><pre>
|
|
#------------------------------------------------------------------------------
|
|
# 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
|
|
#
|
|
foreach w [$win entries] {
|
|
wcb::cbappend $w before insert wcb::checkStrForNum
|
|
}
|
|
|
|
return $win
|
|
}
|
|
</pre></blockquote>
|
|
|
|
<p>The first argument <code>win</code> is the name of the widget, and the
|
|
keyword <code>args</code> represents a list of configuration options and their
|
|
values, just like in the case of the standard Tk widgets. The value
|
|
<code>{3 - 3 - 4}</code> of the <code><a href=
|
|
"mentryWidget.html#body">-body</a></code> option specifies that the mentry
|
|
should consist of two entries of width 3 and one of width 4, separated by
|
|
labels displaying the <code>"-"</code> character.
|
|
|
|
<p>Each mentry widget may have any number of private <b>attributes</b>, which
|
|
can be set and retrieved with the aid of the <code><a href=
|
|
"mentryWidget.html#attrib">attrib</a></code> subcommand of the Tcl procedure
|
|
corresponding to the widget. We use this subcommand to define the
|
|
<code>type</code> attribute of the newly created widget and set it to the value
|
|
<code>"PhoneNumber"</code>. Although this is not strictly necessary, it
|
|
will enable us to distinguish a phone number mentry from other multi-entry
|
|
widgets.
|
|
|
|
<p>The <code>mentry::mentry</code> command registers the <code><a href=
|
|
"wcbRef.html#entrycb">wcb::checkEntryLen</a></code> callback with each entry
|
|
child of the mentry widget to restrict the number of characters that can be
|
|
inserted into it to the initial width specified in the <code>-body</code>
|
|
option. Besides this constraint, we want our entries to accept only
|
|
decimal digits, therefore we use the <code><a href=
|
|
"wcbRef.html#cbappend">wcb::cbappend</a></code> command to <i>add</i> the
|
|
procedure <code><a href="wcbRef.html#entrycb">wcb::checkStrForNum</a></code> to
|
|
the callback list of each entry child. By invoking <code><a href=
|
|
"wcbRef.html#callback">wcb::callback</a></code> instead of
|
|
<code>wcb::cbappend</code> (or <code><a href=
|
|
"wcbRef.html#cbprepend">wcb::cbprepend</a></code>), we would <i>replace</i> the
|
|
callback list with the one consisting of the single element
|
|
<code>wcb::checkStrForNum</code>.
|
|
|
|
<p>Our second procedure outputs a phone number to a mentry widget having a
|
|
<code>type</code> attribute value of <code>"PhoneNumber"</code>:
|
|
|
|
<blockquote><pre>
|
|
#------------------------------------------------------------------------------
|
|
# 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]
|
|
}
|
|
</pre></blockquote>
|
|
|
|
<p>We use the <code><a href="mentryWidget.html#put">put</a></code> subcommand
|
|
of the Tcl procedure corresponding to the mentry widget to display the three
|
|
substrings of the given phone number in the corresponding entries, starting
|
|
with the entry child whose index is specified as the first argument following
|
|
the word <code>put</code>.
|
|
|
|
<p>Next, we need a procedure that returns the phone number contained in a
|
|
mentry widget having a <code>type</code> attribute value of
|
|
<code>"PhoneNumber"</code>:
|
|
|
|
<blockquote><pre>
|
|
#------------------------------------------------------------------------------
|
|
# 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)
|
|
}
|
|
</pre></blockquote>
|
|
|
|
<p>The procedure runs over the indices of the entry children of the given
|
|
mentry widget and invokes the <code><a href=
|
|
"mentryWidget.html#isempty">isempty</a></code> and <code><a href=
|
|
"mentryWidget.html#isfull">isfull</a></code> subcommands of the Tcl command
|
|
corresponding to the given mentry widget. If one of the entries is found
|
|
to be empty or incomplete, the procedure gets its path name by calling the
|
|
<code><a href="mentryWidget.html#entrypath">entrypath</a></code> subcommand,
|
|
sets the focus to that entry, raises an error, and returns the value
|
|
<code>"EMPTY"</code> or <code>"INCOMPL"</code>, respectively. The
|
|
application invoking this procedure should then display an appropriate error
|
|
message corresponding to the return value.
|
|
|
|
<p>Notice that the number <code>3</code> in the <code>for</code> loop above is
|
|
nothing else than <code>[$win <a href=
|
|
"mentryWidget.html#entrycount">entrycount</a>]</code>. Also, it would be
|
|
sufficient to check whether all entry children are full, because an empty entry
|
|
is at the same time incomplete. The preliminary check whether an entry is
|
|
empty is just made for the user's convenience.
|
|
|
|
<p>To build the phone number from the values contained in the entry children,
|
|
we use a temporary array variable and invoke the <code><a href=
|
|
"mentryWidget.html#getarray">getarray</a></code> subcommand, which copies the
|
|
contents of the entries to the corresponding array elements.
|
|
|
|
<p>The last two procedures presented above contain an invocation of the command
|
|
<code>checkIfPhoneNumberMentry</code>, which is implemented as folows:
|
|
|
|
<blockquote><pre>
|
|
#------------------------------------------------------------------------------
|
|
# 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"
|
|
}
|
|
}
|
|
</pre></blockquote>
|
|
|
|
<p>This procedure retrieves the value of the <code>type</code> attribute of its
|
|
argument to check whether the latter denotes a mentry widget for phone numbers
|
|
(remember that this attribute was set to the value <code>"PhoneNumber"</code>
|
|
in the procedure <code>phoneNumberMentry</code>).
|
|
|
|
<p>The four procedures discussed above are implemented in the file
|
|
<code>phonenumber.tcl</code>, contained in the <code>demos</code>
|
|
directory. This script also puts them together to build a small
|
|
application displaying the following figure:
|
|
|
|
<blockquote>
|
|
<p><img src="phonenumber.gif" alt="Phone Number - Please load this image!"
|
|
width=235 height=208>
|
|
</blockquote>
|
|
|
|
<p>Here is the relevant code fragment:
|
|
|
|
<blockquote><pre>
|
|
package require Mentry
|
|
|
|
set title "Phone Number"
|
|
wm title . $title
|
|
|
|
#
|
|
# Get the current windowing system ("x11", "win32", "classic",
|
|
# or "aqua") and add some entries to the Tk option database
|
|
#
|
|
if {[catch {tk windowingsystem} winSys] != 0} {
|
|
switch $::tcl_platform(platform) {
|
|
unix { set winSys x11 }
|
|
windows { set winSys win32 }
|
|
macintosh { set winSys classic }
|
|
}
|
|
}
|
|
switch $winSys {
|
|
x11 { option add *Font "Helvetica -12" }
|
|
classic { option add *background #dedede }
|
|
}
|
|
|
|
#
|
|
# Frame .f with a mentry displaying a phone number
|
|
#
|
|
frame .f
|
|
label .f.l -text "A mentry widget for phone numbers:"
|
|
phoneNumberMentry .f.me -bg white
|
|
pack .f.l .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 .get invoking the procedure getPhoneNumber
|
|
#
|
|
button .get -text "Get from mentry" -command {
|
|
if {[catch {
|
|
set num ""
|
|
set num [getPhoneNumber .f.me]
|
|
} result] != 0} {
|
|
bell
|
|
tk_messageBox -icon error -message $msgs($result) \
|
|
-title $title -type ok
|
|
}
|
|
}
|
|
|
|
#
|
|
# Label .num displaying the result of getPhoneNumber
|
|
#
|
|
label .num -textvariable num
|
|
|
|
. . .
|
|
|
|
putPhoneNumber 1234567890 .f.me
|
|
focus [.f.me entrypath 0]
|
|
</pre></blockquote>
|
|
|
|
|
|
<h3><a name="ex_ethernetAddr"></a>A mentry widget for Ethernet addresses</h3>
|
|
|
|
<p>Ethernet addresses are usuallly written in the form
|
|
<code>"XX:XX:XX:XX:XX:XX"</code>, where each <code>"X"</code> is a hexadecimal
|
|
digit. The file <code>ethernetaddr.tcl</code> in the <code>demos</code>
|
|
directory contains the steps needed to create and use a multi-entry widget for
|
|
displaying and editing Ethernet addresses. It implements the procedures
|
|
<code>ethernetAddrMentry</code>, <code>putEthernetAddr</code>, and
|
|
<code>getEthernetAddr</code>; the last two invoke the helper procedure
|
|
<code>checkIfEthernetAddrMentry</code>, while the first one is implemented as
|
|
follows:
|
|
|
|
<blockquote><pre>
|
|
#------------------------------------------------------------------------------
|
|
# ethernetAddrMentry
|
|
#
|
|
# Creates a new mentry widget win that allows to display and edit Ethernet
|
|
# addresses. Sets the type attribute of the widget to EthernetAddr and returns
|
|
# the name of the newly created widget.
|
|
#------------------------------------------------------------------------------
|
|
proc ethernetAddrMentry {win args} {
|
|
#
|
|
# Create a mentry widget consisting of 6 entry children of
|
|
# width 2, separated by colons, and set its type to EthernetAddr
|
|
#
|
|
eval [list mentry::mentry $win] $args
|
|
$win configure -body {2 : 2 : 2 : 2 : 2 : 2}
|
|
$win attrib type EthernetAddr
|
|
|
|
#
|
|
# Install automatic uppercase conversion and allow only hexadecimal
|
|
# 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
|
|
#
|
|
foreach w [$win entries] {
|
|
wcb::cbappend $w before insert wcb::convStrToUpper \
|
|
{wcb::checkStrForRegExp {^[0-9A-F]*$}}
|
|
}
|
|
|
|
#
|
|
# In the case of a proportionally-spaced font make the
|
|
# entries within the widget a bit wider because the
|
|
# characters A - F need more room than the digits 0 - 9
|
|
#
|
|
if {![font metrics [$win cget -font] -fixed]} {
|
|
foreach w [$win entries] {
|
|
$w configure -width 3
|
|
}
|
|
}
|
|
|
|
return $win
|
|
}
|
|
</pre></blockquote>
|
|
|
|
<p>As explained in the last comment above, in the case of a
|
|
proportionally-spaced font we increase the width of each entry child of the
|
|
multi-entry widget just created to 3. It is important to realize that
|
|
this has no impact on the number of characters accepted by these entries, which
|
|
remains set to the <i>initial</i> width 2 of the entry children, specified in
|
|
the value of the <code>-body</code> configuration option.
|
|
|
|
<p>The procedure <code>putEthernetAddr</code> expects as its first argument a
|
|
string of the form <code>"XX:XX:XX:XX:XX:XX"</code>, where each
|
|
<code>"XX"</code> must be a hexadecimal string in the range <code>0</code> -
|
|
<code>255</code>:
|
|
|
|
<blockquote><pre>
|
|
#------------------------------------------------------------------------------
|
|
# putEthernetAddr
|
|
#
|
|
# Outputs the Ethernet address addr to the mentry widget win of type
|
|
# EthernetAddr. The address must be a string of the form XX:XX:XX:XX:XX:XX,
|
|
# where each XX must be a hexadecimal string in the range 0 - 255. Leading
|
|
# zeros are allowed (but not required), hence the components may have more (but
|
|
# also less) than two characters; the procedure displays them with exactly two
|
|
# digits.
|
|
#------------------------------------------------------------------------------
|
|
proc putEthernetAddr {addr win} {
|
|
set errorMsg "expected an Ethernet address but got \"$addr\""
|
|
|
|
#
|
|
# Check the syntax of addr
|
|
#
|
|
set lst [split $addr :]
|
|
if {[llength $lst] != 6} {
|
|
return -code error $errorMsg
|
|
}
|
|
|
|
#
|
|
# Try to convert the 6 components of addr to hexadecimal
|
|
# strings and check whether they are in the range 0 - 255
|
|
#
|
|
for {set n 0} {$n < 6} {incr n} {
|
|
set val 0x[lindex $lst $n]
|
|
if {[catch {format "%02X" $val} str$n] != 0 || $val < 0 || $val > 255} {
|
|
return -code error $errorMsg
|
|
}
|
|
}
|
|
|
|
#
|
|
# Check the widget and display the properly formatted Ethernet address
|
|
#
|
|
checkIfEthernetAddrMentry $win
|
|
$win put 0 $str0 $str1 $str2 $str3 $str4 $str5
|
|
}
|
|
</pre></blockquote>
|
|
|
|
<p>The procedure <code>getEthernetAddr</code> raises an error if any entry
|
|
child of the given mentry widget is empty. It accepts also entry strings
|
|
of length one, but in the return value all components will have exactly two
|
|
digits:
|
|
|
|
<blockquote><pre>
|
|
#------------------------------------------------------------------------------
|
|
# getEthernetAddr
|
|
#
|
|
# Returns the Ethernet address contained in the mentry widget win of type
|
|
# EthernetAddr.
|
|
#------------------------------------------------------------------------------
|
|
proc getEthernetAddr win {
|
|
#
|
|
# Check the widget
|
|
#
|
|
checkIfEthernetAddrMentry $win
|
|
|
|
#
|
|
# Generate an error if any entry child is empty
|
|
#
|
|
for {set n 0} {$n < 6} {incr n} {
|
|
if {[$win isempty $n]} {
|
|
focus [$win entrypath $n]
|
|
return -code error EMPTY
|
|
}
|
|
}
|
|
|
|
#
|
|
# Return the properly formatted Ethernet address built
|
|
# from the values contained in the entry children
|
|
#
|
|
$win getarray strs
|
|
return [format "%02X:%02X:%02X:%02X:%02X:%02X" \
|
|
0x$strs(0) 0x$strs(1) 0x$strs(2) 0x$strs(3) 0x$strs(4) 0x$strs(5)]
|
|
}
|
|
</pre></blockquote>
|
|
|
|
<p>We will not show the rest of the code here, because it is very similar to
|
|
the one presented in the preceding section. The mentry widget for
|
|
Ethernet addresses looks like in the following figure:
|
|
|
|
<blockquote>
|
|
<p><img src="ethernetaddr.gif" alt=
|
|
"Ethernet Address - Please load this image!" width=257 height=222>
|
|
</blockquote>
|
|
|
|
|
|
<h3><a name="ex_dateTime"></a>Using mentry widgets for date and time</h3>
|
|
|
|
<p>Multi-entry widgets can be used to display and edit date and time in a great
|
|
variety of formats. The Mentry package contains ready-to-use commands for
|
|
this purpose:
|
|
|
|
<ul>
|
|
<li>The procedure <code><a href=
|
|
"mentryDateTime.html#dateMentry">mentry::dateMentry</a></code> creates a
|
|
new mentry widget for displaying and editing a date according to the
|
|
format passed to the command as a three-character string consisting of
|
|
the field descriptor characters <code>"d"</code>, <code>"m"</code>, and
|
|
<code>"y"</code> or <code>"Y"</code>, known from the <code>clock
|
|
format</code> command. Another argument expected by the
|
|
procedure is the string (usually a single character) to be displayed in
|
|
the labels separating the three components of the date.
|
|
|
|
<p>
|
|
<li>Similarly, the procedure <code><a href=
|
|
"mentryDateTime.html#timeMentry">mentry::timeMentry</a></code> creates a
|
|
new mentry widget for displaying and editing a time according to the
|
|
format passed to the command as a two- or three-character string
|
|
consisting of the following field descriptor characters of the
|
|
<code>clock format</code> command: <code>"H"</code> or
|
|
<code>"I"</code>, followed by <code>"M"</code>, and optionally the letter
|
|
<code>"S"</code>. An <code>"H"</code> as first character specifies
|
|
the time format <code>"%H:%M"</code> or <code>"%H:%M:%S"</code> (i.e.,
|
|
with the hour between <code>0</code> and <code>23</code>), while the
|
|
letter <code>"I"</code> stands for <code>"%I:%M %p"</code>
|
|
or <code>"%I:%M:%S %p"</code> (i.e., with AM/PM
|
|
indicator). The procedure expects the separator string (which is
|
|
usually the <code>":"</code> character) as another command-line argument.
|
|
</ul>
|
|
|
|
<p>Before describing the other date- and time-related commands provided by the
|
|
Mentry package, let's see how the above two are invoked in the file
|
|
<code>datetime.tcl</code>, located in the <code>demos</code> directory:
|
|
|
|
<blockquote><pre>
|
|
package require Mentry
|
|
|
|
set title "Date & Time"
|
|
wm title . $title
|
|
|
|
#
|
|
# Get the current windowing system ("x11", "win32", "classic",
|
|
# or "aqua") and add some entries to the Tk option database
|
|
#
|
|
if {[catch {tk windowingsystem} winSys] != 0} {
|
|
switch $::tcl_platform(platform) {
|
|
unix { set winSys x11 }
|
|
windows { set winSys win32 }
|
|
macintosh { set winSys classic }
|
|
}
|
|
}
|
|
switch $winSys {
|
|
x11 { option add *Font "Helvetica -12" }
|
|
classic { option add *background #dedede }
|
|
}
|
|
|
|
#
|
|
# Date and time formats supported by this demo
|
|
# script and the corresponding field separators
|
|
#
|
|
array set dateFmts {0 mdy 1 dmy 2 Ymd}
|
|
array set dateSeps {0 / 1 . 2 - }
|
|
array set timeFmts {0 IMS 1 HMS}
|
|
array set timeSeps {0 : 1 : }
|
|
|
|
#
|
|
# Choose the date & time formats; don't use the %p field descriptor
|
|
# for displaying the AM/PM indicator, because it doesn't work on
|
|
# UNIX if Tcl/Tk 8.4 or higher is used in a non-default locale
|
|
#
|
|
wm withdraw .
|
|
set clockVal [clock seconds]
|
|
if {[clock format $clockVal -format "%H"] < 12} {
|
|
set meridian AM
|
|
} else {
|
|
set meridian PM
|
|
}
|
|
set dateIdx [tk_dialog .choice $title "Please choose a date format" {} -1 \
|
|
[clock format $clockVal -format "%m/%d/%y"] \
|
|
[clock format $clockVal -format "%d.%m.%y"] \
|
|
[clock format $clockVal -format "%Y-%m-%d"]]
|
|
set timeIdx [tk_dialog .choice $title "Please choose a time format" {} -1 \
|
|
[clock format $clockVal -format "%I:%M:%S $meridian"] \
|
|
[clock format $clockVal -format "%H:%M:%S"]]
|
|
wm deiconify .
|
|
|
|
#
|
|
# Frame .f with mentries displaying the date & time
|
|
#
|
|
frame .f
|
|
label .f.lDate -text "Date: "
|
|
mentry::dateMentry .f.date $dateFmts($dateIdx) $dateSeps($dateIdx) \
|
|
-justify center -bg white
|
|
frame .f.gap -width 10
|
|
label .f.lTime -text "Time: "
|
|
mentry::timeMentry .f.time $timeFmts($timeIdx) $timeSeps($timeIdx) \
|
|
-justify center -bg white
|
|
pack .f.lDate .f.date .f.gap .f.lTime .f.time -side left
|
|
</pre></blockquote>
|
|
|
|
<p>Before displaying the main window, the script lets the user choose one out
|
|
of three date and one out of two time formats. The corresponding
|
|
command-line arguments passed to <code>mentry::dateMentry</code> and
|
|
<code>mentry::timeMentry</code> are taken from the arrays
|
|
<code>dateFmts</code>, <code>dateSeps</code>, <code>timeFmts</code>, and
|
|
<code>timeSeps</code>.
|
|
|
|
<p>The following figure corresponds to the choices <code>dateIdx =
|
|
2</code> and <code>timeIdx = 1</code>:
|
|
|
|
<blockquote>
|
|
<p><img src="datetime.gif" alt="Date & Time - Please load this image!"
|
|
width=254 height=188>
|
|
</blockquote>
|
|
|
|
<p>The Mentry package exports two further commands for date and time mentries:
|
|
|
|
<ul>
|
|
<li>The procedure <code><a href=
|
|
"mentryDateTime.html#putClockVal">mentry::putClockVal</a></code> outputs
|
|
the date or time corresponding to an integer clock value specified as its
|
|
first argument to a date or time mentry widget, passed to it as the
|
|
second parameter. Like the  <code>clock format</code>
|
|
command, the procedure accepts the optional argument pair
|
|
<code>-gmt <i>boolean</i></code>.
|
|
|
|
<p>
|
|
<li>The procedure <code><a href=
|
|
"mentryDateTime.html#getClockVal">mentry::getClockVal</a></code> returns
|
|
the clock value corresponding to the date or time contained in the date
|
|
or time mentry specified as its first argument. Like the
|
|
 <code>clock scan</code> command, the procedure accepts the
|
|
optional argument pairs <code>-base <i>clockValue</i></code>
|
|
and <code>-gmt <i>boolean</i></code>. On failure, the
|
|
procedure sets the focus to the first erronous entry child, generates an
|
|
error, and returns one of the values contained in the following code
|
|
fragment taken from the script <code>datetime.tcl</code>:
|
|
|
|
<blockquote><pre>
|
|
#
|
|
# Message strings corresponding to the values
|
|
# returned by mentry::getClockVal on failure
|
|
#
|
|
array set msgs {
|
|
EMPTY "Field value missing"
|
|
BAD "Invalid field value"
|
|
BAD_DATE "Invalid date"
|
|
BAD_YEAR "Unsupported year"
|
|
}
|
|
</pre></blockquote>
|
|
|
|
<p>The string <code>"EMPTY"</code> is returned if any entry child (except
|
|
the one containing the seconds) was found to be empty. The value
|
|
<code>"BAD"</code> means a day, month, or hour value of <code>0</code>
|
|
(the hour must not be <code>0</code> if the AM/PM indicator is
|
|
present). The string <code>"BAD_DATE"</code> is returned when the
|
|
<year, month, day> triple is invalid (note that the procedure is
|
|
aware of leap years). Finally, even if this triple is valid, the
|
|
conversion (made with the aid of the <code>clock scan</code>
|
|
command) can fail because of an unsupported year value (e.g., between
|
|
<code>38</code> and <code>70</code>); in this case the string
|
|
<code>"BAD_YEAR"</code> is returned.
|
|
</ul>
|
|
|
|
<p>The demo script <code>datetime.tcl</code> invokes the last two commands as
|
|
follows:
|
|
|
|
<blockquote><pre>
|
|
#
|
|
# Button .get invoking the procedure mentry::getClockVal
|
|
#
|
|
button .get -text "Get from mentries" -command {
|
|
if {[catch {
|
|
set dateTime ""
|
|
set base [mentry::getClockVal .f.date]
|
|
set clockVal [mentry::getClockVal .f.time -base $base]
|
|
set dateTime [clock format $clockVal -format "%c"]
|
|
} result] != 0} {
|
|
bell
|
|
tk_messageBox -icon error -message $msgs($result) \
|
|
-title $title -type ok
|
|
}
|
|
}
|
|
|
|
#
|
|
# Label .dateTime displaying the result of mentry::getClockVal
|
|
#
|
|
label .dateTime -textvariable dateTime
|
|
|
|
. . .
|
|
|
|
set clockVal [clock seconds]
|
|
mentry::putClockVal $clockVal .f.date
|
|
mentry::putClockVal $clockVal .f.time
|
|
focus [.f.date entrypath 0]
|
|
</pre></blockquote>
|
|
|
|
<p>To obtain the clock value from the mentry widgets <code>.f.date</code> and
|
|
<code>.f.time</code>, we first pass the name of the date mentry to the command
|
|
<code>mentry::getClockVal</code> and then use the result as the value of the
|
|
<code>-base</code> option when passing the name of the time mentry to the same
|
|
procedure.
|
|
|
|
<div align=center>
|
|
<p><a href="#contents">Contents</a>
|
|
<a href="index.html">Start page</a>
|
|
</div>
|
|
</body>
|
|
</html>
|