summaryrefslogtreecommitdiff
path: root/iwidgets/generic
diff options
context:
space:
mode:
authorKeith Seitz <keiths@redhat.com>2002-09-24 23:50:31 +0000
committerKeith Seitz <keiths@redhat.com>2002-09-24 23:50:31 +0000
commit43375e54d64ecea0b356c82d72b29fd95dd54cc9 (patch)
tree7582d7bb623964e848d993dde740802e40a748b0 /iwidgets/generic
parent5a88d945c95d8c15e31bf74fc9850b8c01fdeaec (diff)
downloadgdb-43375e54d64ecea0b356c82d72b29fd95dd54cc9.tar.gz
import iwidgets 4.0.1tcltk840-20020924-branchpoint
Diffstat (limited to 'iwidgets/generic')
-rw-r--r--iwidgets/generic/buttonbox.itk571
-rw-r--r--iwidgets/generic/calendar.itk983
-rw-r--r--iwidgets/generic/canvasprintbox.itk1111
-rw-r--r--iwidgets/generic/canvasprintdialog.itk155
-rw-r--r--iwidgets/generic/checkbox.itk341
-rw-r--r--iwidgets/generic/colors.itcl209
-rw-r--r--iwidgets/generic/combobox.itk1443
-rw-r--r--iwidgets/generic/dateentry.itk424
-rw-r--r--iwidgets/generic/datefield.itk1021
-rw-r--r--iwidgets/generic/dialog.itk92
-rw-r--r--iwidgets/generic/dialogshell.itk350
-rw-r--r--iwidgets/generic/disjointlistbox.itk529
-rw-r--r--iwidgets/generic/entryfield.itk603
-rw-r--r--iwidgets/generic/extbutton.itk439
-rw-r--r--iwidgets/generic/extfileselectionbox.itk1187
-rw-r--r--iwidgets/generic/extfileselectiondialog.itk182
-rw-r--r--iwidgets/generic/feedback.itk212
-rw-r--r--iwidgets/generic/fileselectionbox.itk1296
-rw-r--r--iwidgets/generic/fileselectiondialog.itk181
-rw-r--r--iwidgets/generic/finddialog.itk488
-rw-r--r--iwidgets/generic/hierarchy.itk1983
-rw-r--r--iwidgets/generic/hyperhelp.itk508
-rw-r--r--iwidgets/generic/labeledframe.itk496
-rw-r--r--iwidgets/generic/labeledwidget.itk445
-rw-r--r--iwidgets/generic/mainwindow.itk313
-rw-r--r--iwidgets/generic/menubar.itk2267
-rw-r--r--iwidgets/generic/messagebox.itk399
-rw-r--r--iwidgets/generic/messagedialog.itk144
-rw-r--r--iwidgets/generic/notebook.itk946
-rw-r--r--iwidgets/generic/optionmenu.itk664
-rw-r--r--iwidgets/generic/pane.itk128
-rw-r--r--iwidgets/generic/panedwindow.itk942
-rw-r--r--iwidgets/generic/promptdialog.itk199
-rw-r--r--iwidgets/generic/pushbutton.itk356
-rw-r--r--iwidgets/generic/radiobox.itk427
-rw-r--r--iwidgets/generic/regexpfield.itk455
-rw-r--r--iwidgets/generic/roman.itcl29
-rw-r--r--iwidgets/generic/scopedobject.itcl181
-rw-r--r--iwidgets/generic/scrolledcanvas.itk477
-rw-r--r--iwidgets/generic/scrolledframe.itk250
-rw-r--r--iwidgets/generic/scrolledhtml.itk2521
-rw-r--r--iwidgets/generic/scrolledlistbox.itk732
-rw-r--r--iwidgets/generic/scrolledtext.itk501
-rw-r--r--iwidgets/generic/scrolledwidget.itk376
-rw-r--r--iwidgets/generic/selectionbox.itk560
-rw-r--r--iwidgets/generic/selectiondialog.itk233
-rw-r--r--iwidgets/generic/shell.itk375
-rw-r--r--iwidgets/generic/spindate.itk693
-rw-r--r--iwidgets/generic/spinint.itk237
-rw-r--r--iwidgets/generic/spinner.itk448
-rw-r--r--iwidgets/generic/spintime.itk527
-rw-r--r--iwidgets/generic/tabnotebook.itk1105
-rw-r--r--iwidgets/generic/tabset.itk2753
-rw-r--r--iwidgets/generic/tclIndex1372
-rw-r--r--iwidgets/generic/timeentry.itk398
-rw-r--r--iwidgets/generic/timefield.itk1018
-rw-r--r--iwidgets/generic/toolbar.itk983
-rw-r--r--iwidgets/generic/unknownimage.gifbin0 -> 472 bytes
-rw-r--r--iwidgets/generic/watch.itk626
59 files changed, 38884 insertions, 0 deletions
diff --git a/iwidgets/generic/buttonbox.itk b/iwidgets/generic/buttonbox.itk
new file mode 100644
index 00000000000..dabada368cc
--- /dev/null
+++ b/iwidgets/generic/buttonbox.itk
@@ -0,0 +1,571 @@
+#
+# Buttonbox
+# ----------------------------------------------------------------------
+# Manages a framed area with Motif style buttons. The button box can
+# be configured either horizontally or vertically.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+# Bret A. Schuhmacher EMAIL: bas@wn.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Buttonbox {
+ keep -background -cursor -foreground
+}
+
+# ------------------------------------------------------------------
+# BUTTONBOX
+# ------------------------------------------------------------------
+itcl::class iwidgets::Buttonbox {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -pady padY Pad 5
+ itk_option define -padx padX Pad 5
+ itk_option define -orient orient Orient "horizontal"
+ itk_option define -foreground foreground Foreground black
+
+ public method index {args}
+ public method add {args}
+ public method insert {args}
+ public method delete {args}
+ public method default {args}
+ public method hide {args}
+ public method show {args}
+ public method invoke {args}
+ public method buttonconfigure {args}
+ public method buttoncget {index option}
+
+ private method _positionButtons {}
+ private method _setBoxSize {{when later}}
+ private method _getMaxWidth {}
+ private method _getMaxHeight {}
+
+ private variable _resizeFlag {} ;# Flag for resize needed.
+ private variable _buttonList {} ;# List of all buttons in box.
+ private variable _displayList {} ;# List of displayed buttons.
+ private variable _unique 0 ;# Counter for button widget ids.
+}
+
+namespace eval iwidgets::Buttonbox {
+ #
+ # Set up some class level bindings for map and configure events.
+ #
+ bind bbox-map <Map> [itcl::code %W _setBoxSize]
+ bind bbox-config <Configure> [itcl::code %W _positionButtons]
+}
+
+#
+# Provide a lowercased access method for the Buttonbox class.
+#
+proc ::iwidgets::buttonbox {pathName args} {
+ uplevel ::iwidgets::Buttonbox $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::constructor {args} {
+ #
+ # Add Configure bindings for geometry management.
+ #
+ bindtags $itk_component(hull) \
+ [linsert [bindtags $itk_component(hull)] 0 bbox-map]
+ bindtags $itk_component(hull) \
+ [linsert [bindtags $itk_component(hull)] 1 bbox-config]
+
+ pack propagate $itk_component(hull) no
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::destructor {} {
+ if {$_resizeFlag != ""} {after cancel $_resizeFlag}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -pady
+#
+# Pad the y space between the button box frame and the hull.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Buttonbox::pady {
+ _setBoxSize
+}
+
+# ------------------------------------------------------------------
+# OPTION: -padx
+#
+# Pad the x space between the button box frame and the hull.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Buttonbox::padx {
+ _setBoxSize
+}
+
+# ------------------------------------------------------------------
+# OPTION: -orient
+#
+# Position buttons either horizontally or vertically.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Buttonbox::orient {
+ switch $itk_option(-orient) {
+ "horizontal" -
+ "vertical" {
+ _setBoxSize
+ }
+
+ default {
+ error "bad orientation option \"$itk_option(-orient)\",\
+ should be either horizontal or vertical"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: index index
+#
+# Searches the buttons in the box for the one with the requested tag,
+# numerical index, keyword "end" or "default". Returns the button's
+# tag if found, otherwise error.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::index {index} {
+ if {[llength $_buttonList] > 0} {
+ if {[regexp {(^[0-9]+$)} $index]} {
+ if {$index < [llength $_buttonList]} {
+ return $index
+ } else {
+ error "Buttonbox index \"$index\" is out of range"
+ }
+
+ } elseif {$index == "end"} {
+ return [expr {[llength $_buttonList] - 1}]
+
+ } elseif {$index == "default"} {
+ foreach knownButton $_buttonList {
+ if {[$itk_component($knownButton) cget -defaultring]} {
+ return [lsearch -exact $_buttonList $knownButton]
+ }
+ }
+
+ error "Buttonbox \"$itk_component(hull)\" has no default"
+
+ } else {
+ if {[set idx [lsearch $_buttonList $index]] != -1} {
+ return $idx
+ }
+
+ error "bad Buttonbox index \"$index\": must be number, end,\
+ default, or pattern"
+ }
+
+ } else {
+ error "Buttonbox \"$itk_component(hull)\" has no buttons"
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: add tag ?option value option value ...?
+#
+# Add the specified button to the button box. All PushButton options
+# are allowed. New buttons are added to the list of buttons and the
+# list of displayed buttons. The PushButton path name is returned.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::add {tag args} {
+ itk_component add $tag {
+ iwidgets::Pushbutton $itk_component(hull).[incr _unique]
+ } {
+ usual
+ rename -highlightbackground -background background Background
+ }
+
+ if {$args != ""} {
+ uplevel $itk_component($tag) configure $args
+ }
+
+ lappend _buttonList $tag
+ lappend _displayList $tag
+
+ _setBoxSize
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert index tag ?option value option value ...?
+#
+# Insert the specified button in the button box just before the one
+# given by index. All PushButton options are allowed. New buttons
+# are added to the list of buttons and the list of displayed buttons.
+# The PushButton path name is returned.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::insert {index tag args} {
+ itk_component add $tag {
+ iwidgets::Pushbutton $itk_component(hull).[incr _unique]
+ } {
+ usual
+ rename -highlightbackground -background background Background
+ }
+
+ if {$args != ""} {
+ uplevel $itk_component($tag) configure $args
+ }
+
+ set index [index $index]
+ set _buttonList [linsert $_buttonList $index $tag]
+ set _displayList [linsert $_displayList $index $tag]
+
+ _setBoxSize
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete index
+#
+# Delete the specified button from the button box.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::delete {index} {
+ set index [index $index]
+ set tag [lindex $_buttonList $index]
+
+ destroy $itk_component($tag)
+
+ set _buttonList [lreplace $_buttonList $index $index]
+
+ if {[set dind [lsearch $_displayList $tag]] != -1} {
+ set _displayList [lreplace $_displayList $dind $dind]
+ }
+
+ _setBoxSize
+ update idletasks
+}
+
+# ------------------------------------------------------------------
+# METHOD: default index
+#
+# Sets the default to the push button given by index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::default {index} {
+ set index [index $index]
+
+ set defbtn [lindex $_buttonList $index]
+
+ foreach knownButton $_displayList {
+ if {$knownButton == $defbtn} {
+ $itk_component($knownButton) configure -defaultring yes
+ } else {
+ $itk_component($knownButton) configure -defaultring no
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: hide index
+#
+# Hide the push button given by index. This doesn't remove the button
+# permanently from the display list, just inhibits its display.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::hide {index} {
+ set index [index $index]
+ set tag [lindex $_buttonList $index]
+
+ if {[set dind [lsearch $_displayList $tag]] != -1} {
+ place forget $itk_component($tag)
+ set _displayList [lreplace $_displayList $dind $dind]
+
+ _setBoxSize
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: show index
+#
+# Displays a previously hidden push button given by index. Check if
+# the button is already in the display list. If not then add it back
+# at it's original location and redisplay.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::show {index} {
+ set index [index $index]
+ set tag [lindex $_buttonList $index]
+
+ if {[lsearch $_displayList $tag] == -1} {
+ set _displayList [linsert $_displayList $index $tag]
+
+ _setBoxSize
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: invoke ?index?
+#
+# Invoke the command associated with a push button. If no arguments
+# are given then the default button is invoked, otherwise the argument
+# is expected to be a button index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::invoke {args} {
+ if {[llength $args] == 0} {
+ $itk_component([lindex $_buttonList [index default]]) invoke
+
+ } else {
+ $itk_component([lindex $_buttonList [index [lindex $args 0]]]) \
+ invoke
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: buttonconfigure index ?option? ?value option value ...?
+#
+# Configure a push button given by index. This method allows
+# configuration of pushbuttons from the Buttonbox level. The options
+# may have any of the values accepted by the add method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::buttonconfigure {index args} {
+ set tag [lindex $_buttonList [index $index]]
+
+ set retstr [uplevel $itk_component($tag) configure $args]
+
+ _setBoxSize
+
+ return $retstr
+}
+
+# ------------------------------------------------------------------
+# METHOD: buttonccget index option
+#
+# Return value of option for push button given by index. Option may
+# have any of the values accepted by the add method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::buttoncget {index option} {
+ set tag [lindex $_buttonList [index $index]]
+
+ set retstr [uplevel $itk_component($tag) cget [list $option]]
+
+ return $retstr
+}
+
+# -----------------------------------------------------------------
+# PRIVATE METHOD: _getMaxWidth
+#
+# Returns the required width of the largest button.
+# -----------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::_getMaxWidth {} {
+ set max 0
+
+ foreach tag $_displayList {
+ set w [winfo reqwidth $itk_component($tag)]
+
+ if {$w > $max} {
+ set max $w
+ }
+ }
+
+ return $max
+}
+
+# -----------------------------------------------------------------
+# PRIVATE METHOD: _getMaxHeight
+#
+# Returns the required height of the largest button.
+# -----------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::_getMaxHeight {} {
+ set max 0
+
+ foreach tag $_displayList {
+ set h [winfo reqheight $itk_component($tag)]
+
+ if {$h > $max} {
+ set max $h
+ }
+ }
+
+ return $max
+}
+
+# ------------------------------------------------------------------
+# METHOD: _setBoxSize ?when?
+#
+# Sets the proper size of the frame surrounding all the buttons.
+# If "when" is "now", the change is applied immediately. If it is
+# "later" or it is not specified, then the change is applied later,
+# when the application is idle.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::_setBoxSize {{when later}} {
+ if {[winfo ismapped $itk_component(hull)]} {
+ if {$when == "later"} {
+ if {$_resizeFlag == ""} {
+ set _resizeFlag [after idle [itcl::code $this _setBoxSize now]]
+ }
+ return
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ set _resizeFlag ""
+
+ set numBtns [llength $_displayList]
+
+ if {$itk_option(-orient) == "horizontal"} {
+ set minw [expr {$numBtns * [_getMaxWidth] \
+ + ($numBtns+1) * $itk_option(-padx)}]
+ set minh [expr {[_getMaxHeight] + 2 * $itk_option(-pady)}]
+
+ } else {
+ set minw [expr {[_getMaxWidth] + 2 * $itk_option(-padx)}]
+ set minh [expr {$numBtns * [_getMaxHeight] \
+ + ($numBtns+1) * $itk_option(-pady)}]
+ }
+
+ #
+ # Remove the configure event bindings on the hull while we adjust the
+ # width/height and re-position the buttons. Once we're through, we'll
+ # update and reinstall them. This prevents double calls to position
+ # the buttons.
+ #
+ set tags [bindtags $itk_component(hull)]
+ if {[set i [lsearch $tags bbox-config]] != -1} {
+ set tags [lreplace $tags $i $i]
+ bindtags $itk_component(hull) $tags
+ }
+
+ component hull configure -width $minw -height $minh
+
+ update idletasks
+
+ _positionButtons
+
+ bindtags $itk_component(hull) [linsert $tags 0 bbox-config]
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: _positionButtons
+#
+# This method is responsible setting the width/height of all the
+# displayed buttons to the same value and for placing all the buttons
+# in equidistant locations.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Buttonbox::_positionButtons {} {
+ set bf $itk_component(hull)
+ set numBtns [llength $_displayList]
+
+ #
+ # First, determine the common width and height for all the
+ # displayed buttons.
+ #
+ if {$numBtns > 0} {
+ set bfWidth [winfo width $itk_component(hull)]
+ set bfHeight [winfo height $itk_component(hull)]
+
+ if {$bfWidth >= [winfo reqwidth $itk_component(hull)]} {
+ set _btnWidth [_getMaxWidth]
+
+ } else {
+ if {$itk_option(-orient) == "horizontal"} {
+ set _btnWidth [expr {$bfWidth / $numBtns}]
+ } else {
+ set _btnWidth $bfWidth
+ }
+ }
+
+ if {$bfHeight >= [winfo reqheight $itk_component(hull)]} {
+ set _btnHeight [_getMaxHeight]
+
+ } else {
+ if {$itk_option(-orient) == "vertical"} {
+ set _btnHeight [expr {$bfHeight / $numBtns}]
+ } else {
+ set _btnHeight $bfHeight
+ }
+ }
+ }
+
+ #
+ # Place the buttons at the proper locations.
+ #
+ if {$numBtns > 0} {
+ if {$itk_option(-orient) == "horizontal"} {
+ set leftover [expr {[winfo width $bf] \
+ - 2 * $itk_option(-padx) - $_btnWidth * $numBtns}]
+
+ if {$numBtns > 0} {
+ set offset [expr {$leftover / ($numBtns + 1)}]
+ } else {
+ set offset 0
+ }
+ if {$offset < 0} {set offset 0}
+
+ set xDist [expr {$itk_option(-padx) + $offset}]
+ set incrAmount [expr {$_btnWidth + $offset}]
+
+ foreach button $_displayList {
+ place $itk_component($button) -anchor w \
+ -x $xDist -rely .5 -y 0 -relx 0 \
+ -width $_btnWidth -height $_btnHeight
+
+ set xDist [expr {$xDist + $incrAmount}]
+ }
+
+ } else {
+ set leftover [expr {[winfo height $bf] \
+ - 2 * $itk_option(-pady) - $_btnHeight * $numBtns}]
+
+ if {$numBtns > 0} {
+ set offset [expr {$leftover / ($numBtns + 1)}]
+ } else {
+ set offset 0
+ }
+ if {$offset < 0} {set offset 0}
+
+ set yDist [expr {$itk_option(-pady) + $offset}]
+ set incrAmount [expr {$_btnHeight + $offset}]
+
+ foreach button $_displayList {
+ place $itk_component($button) -anchor n \
+ -y $yDist -relx .5 -x 0 -rely 0 \
+ -width $_btnWidth -height $_btnHeight
+
+ set yDist [expr {$yDist + $incrAmount}]
+ }
+ }
+ }
+}
+
+
diff --git a/iwidgets/generic/calendar.itk b/iwidgets/generic/calendar.itk
new file mode 100644
index 00000000000..d263f54acf9
--- /dev/null
+++ b/iwidgets/generic/calendar.itk
@@ -0,0 +1,983 @@
+#
+# Calendar
+# ----------------------------------------------------------------------
+# Implements a calendar widget for the selection of a date. It displays
+# a single month at a time. Buttons exist on the top to change the
+# month in effect turning th pages of a calendar. As a page is turned,
+# the dates for the month are modified. Selection of a date visually
+# marks that date. The selected value can be monitored via the
+# -command option or just retrieved using the get method. Methods also
+# exist to select a date and show a particular month. The option set
+# allows the calendars appearance to take on many forms.
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts E-mail: mulferts@austin.dsccc.com
+#
+# ACKNOWLEDGEMENTS: Michael McLennan E-mail: mmclennan@lucent.com
+#
+# This code is an [incr Tk] port of the calendar code shown in Michael
+# J. McLennan's book "Effective Tcl" from Addison Wesley. Small
+# modificiations were made to the logic here and there to make it a
+# mega-widget and the command and option interface was expanded to make
+# it even more configurable, but the underlying logic is the same.
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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 Calendar {
+ keep -background -cursor
+}
+
+# ------------------------------------------------------------------
+# CALENDAR
+# ------------------------------------------------------------------
+itcl::class iwidgets::Calendar {
+ inherit itk::Widget
+
+ constructor {args} {}
+
+ itk_option define -days days Days {Su Mo Tu We Th Fr Sa}
+ itk_option define -command command Command {}
+ itk_option define -forwardimage forwardImage Image {}
+ itk_option define -backwardimage backwardImage Image {}
+ itk_option define -weekdaybackground weekdayBackground Background \#d9d9d9
+ itk_option define -weekendbackground weekendBackground Background \#d9d9d9
+ itk_option define -outline outline Outline \#d9d9d9
+ itk_option define -buttonforeground buttonForeground Foreground blue
+ itk_option define -foreground foreground Foreground black
+ itk_option define -selectcolor selectColor Foreground red
+ itk_option define -selectthickness selectThickness SelectThickness 3
+ itk_option define -titlefont titleFont Font \
+ -*-helvetica-bold-r-normal--*-140-*
+ itk_option define -dayfont dayFont Font \
+ -*-helvetica-medium-r-normal--*-120-*
+ itk_option define -datefont dateFont Font \
+ -*-helvetica-medium-r-normal--*-120-*
+ itk_option define -currentdatefont currentDateFont Font \
+ -*-helvetica-bold-r-normal--*-120-*
+ itk_option define -startday startDay Day sunday
+ itk_option define -int int DateFormat no
+
+ public method get {{format "-string"}} ;# Returns the selected date
+ public method select {{date_ "now"}} ;# Selects date, moving select ring
+ public method show {{date_ "now"}} ;# Displays a specific date
+
+ protected method _drawtext {canvas_ day_ date_ now_ x0_ y0_ x1_ y1_}
+
+ private method _change {delta_}
+ private method _configureHandler {}
+ private method _redraw {}
+ private method _days {{wmax {}}}
+ private method _layout {time_}
+ private method _select {date_}
+ private method _selectEvent {date_}
+ private method _adjustday {day_}
+ private method _percentSubst {pattern_ string_ subst_}
+
+ private variable _time {}
+ private variable _selected {}
+ private variable _initialized 0
+ private variable _offset 0
+ private variable _format {}
+}
+
+#
+# Provide a lowercased access method for the Calendar class.
+#
+proc ::iwidgets::calendar {pathName args} {
+ uplevel ::iwidgets::Calendar $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Calendar.width 200 widgetDefault
+option add *Calendar.height 165 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::constructor {args} {
+ #
+ # Create the canvas which displays each page of the calendar.
+ #
+ itk_component add page {
+ canvas $itk_interior.page
+ } {
+ keep -background -cursor -width -height
+ }
+ pack $itk_component(page) -expand yes -fill both
+
+ #
+ # Create the forward and backward buttons. Rather than pack
+ # them directly in the hull, we'll waittill later and make
+ # them canvas window items.
+ #
+ itk_component add backward {
+ button $itk_component(page).backward \
+ -command [itcl::code $this _change -1]
+ } {
+ keep -background -cursor
+ }
+
+ itk_component add forward {
+ button $itk_component(page).forward \
+ -command [itcl::code $this _change +1]
+ } {
+ keep -background -cursor
+ }
+
+ #
+ # Set the initial time to now.
+ #
+ set _time [clock seconds]
+
+ #
+ # Bind to the configure event which will be used to redraw
+ # the calendar and display the month.
+ #
+ bind $itk_component(page) <Configure> [itcl::code $this _configureHandler]
+
+ #
+ # Evaluate the option arguments.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+# ------------------------------------------------------------------
+# OPTION: -int
+#
+# Added by Mark Alston 2001/10/21
+#
+# Allows for the use of dates in "international" format: YYYY-MM-DD.
+# It must be a boolean value.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::int {
+ switch $itk_option(-int) {
+ 1 - yes - true - on {
+ set itk_option(-int) yes
+ }
+ 0 - no - false - off {
+ set itk_option(-int) no
+ }
+ default {
+ error "bad int option \"$itk_option(-int)\": should be boolean"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -command
+#
+# Sets the selection command for the calendar. When the user
+# selects a date on the calendar, the date is substituted in
+# place of "%d" in this command, and the command is executed.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::command {}
+
+# ------------------------------------------------------------------
+# OPTION: -days
+#
+# The days option takes a list of values to set the text used to display the
+# days of the week header above the dates. The default value is
+# {Su Mo Tu We Th Fr Sa}.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::days {
+ if {$_initialized} {
+ if {[$itk_component(page) find withtag days] != {}} {
+ $itk_component(page) delete days
+ _days
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -backwardimage
+#
+# Specifies a image to be displayed on the backwards calendar
+# button. If none is specified, a default is provided.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::backwardimage {
+
+ #
+ # If no image is given, then we'll use the default image.
+ #
+ if {$itk_option(-backwardimage) == {}} {
+
+ #
+ # If the default image hasn't yet been created, then we
+ # need to create it.
+ #
+ if {[lsearch [image names] $this-backward] == -1} {
+ image create bitmap $this-backward \
+ -foreground $itk_option(-buttonforeground) -data {
+ #define back_width 16
+ #define back_height 16
+ static unsigned char back_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x30,
+ 0xe0, 0x38, 0xf0, 0x3c, 0xf8, 0x3e, 0xfc, 0x3f,
+ 0xfc, 0x3f, 0xf8, 0x3e, 0xf0, 0x3c, 0xe0, 0x38,
+ 0xc0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ }
+ }
+
+ #
+ # Configure the button to use the default image.
+ #
+ $itk_component(backward) configure -image $this-backward
+
+ #
+ # Else, an image has been specified. First, we'll need to make sure
+ # the image really exists before configuring the button to use it.
+ # If it doesn't generate an error.
+ #
+ } else {
+ if {[lsearch [image names] $itk_option(-backwardimage)] != -1} {
+ $itk_component(backward) configure \
+ -image $itk_option(-backwardimage)
+ } else {
+ error "bad image name \"$itk_option(-backwardimage)\":\
+ image does not exist"
+ }
+
+ #
+ # If we previously created a default image, we'll just remove it.
+ #
+ if {[lsearch [image names] $this-backward] != -1} {
+ image delete $this-backward
+ }
+ }
+}
+
+
+# ------------------------------------------------------------------
+# OPTION: -forwardimage
+#
+# Specifies a image to be displayed on the forwards calendar
+# button. If none is specified, a default is provided.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::forwardimage {
+
+ #
+ # If no image is given, then we'll use the default image.
+ #
+ if {$itk_option(-forwardimage) == {}} {
+
+ #
+ # If the default image hasn't yet been created, then we
+ # need to create it.
+ #
+ if {[lsearch [image names] $this-forward] == -1} {
+ image create bitmap $this-forward \
+ -foreground $itk_option(-buttonforeground) -data {
+ #define fwd_width 16
+ #define fwd_height 16
+ static unsigned char fwd_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03,
+ 0x1c, 0x07, 0x3c, 0x0f, 0x7c, 0x1f, 0xfc, 0x3f,
+ 0xfc, 0x3f, 0x7c, 0x1f, 0x3c, 0x0f, 0x1c, 0x07,
+ 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ }
+ }
+
+ #
+ # Configure the button to use the default image.
+ #
+ $itk_component(forward) configure -image $this-forward
+
+ #
+ # Else, an image has been specified. First, we'll need to make sure
+ # the image really exists before configuring the button to use it.
+ # If it doesn't generate an error.
+ #
+ } else {
+ if {[lsearch [image names] $itk_option(-forwardimage)] != -1} {
+ $itk_component(forward) configure \
+ -image $itk_option(-forwardimage)
+ } else {
+ error "bad image name \"$itk_option(-forwardimage)\":\
+ image does not exist"
+ }
+
+ #
+ # If we previously created a default image, we'll just remove it.
+ #
+ if {[lsearch [image names] $this-forward] != -1} {
+ image delete $this-forward
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -weekdaybackground
+#
+# Specifies the background for the weekdays which allows it to
+# be visually distinguished from the weekend.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::weekdaybackground {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure weekday \
+ -fill $itk_option(-weekdaybackground)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -weekendbackground
+#
+# Specifies the background for the weekdays which allows it to
+# be visually distinguished from the weekdays.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::weekendbackground {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure weekend \
+ -fill $itk_option(-weekendbackground)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -foreground
+#
+# Specifies the foreground color for the textual items, buttons,
+# and divider on the calendar.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::foreground {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure text \
+ -fill $itk_option(-foreground)
+ $itk_component(page) itemconfigure line \
+ -fill $itk_option(-foreground)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -outline
+#
+# Specifies the outline color used to surround the date text.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::outline {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure square \
+ -outline $itk_option(-outline)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -buttonforeground
+#
+# Specifies the foreground color of the forward and backward buttons.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::buttonforeground {
+ if {$_initialized} {
+ if {$itk_option(-forwardimage) == {}} {
+ if {[lsearch [image names] $this-forward] != -1} {
+ $this-forward configure \
+ -foreground $itk_option(-buttonforeground)
+ }
+ } else {
+ $itk_component(forward) configure \
+ -foreground $itk_option(-buttonforeground)
+ }
+
+ if {$itk_option(-backwardimage) == {}} {
+ if {[lsearch [image names] $this-backward] != -1} {
+ $this-backward configure \
+ -foreground $itk_option(-buttonforeground)
+ }
+ } else {
+ $itk_component(-backward) configure \
+ -foreground $itk_option(-buttonforeground)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectcolor
+#
+# Specifies the color of the ring displayed that distinguishes the
+# currently selected date.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::selectcolor {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure $_selected-sensor \
+ -outline $itk_option(-selectcolor)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectthickness
+#
+# Specifies the thickness of the ring displayed that distinguishes
+# the currently selected date.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::selectthickness {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure $_selected-sensor \
+ -width $itk_option(-selectthickness)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -titlefont
+#
+# Specifies the font used for the title text that consists of the
+# month and year.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::titlefont {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure title \
+ -font $itk_option(-titlefont)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -datefont
+#
+# Specifies the font used for the date text that consists of the
+# day of the month.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::datefont {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure date \
+ -font $itk_option(-datefont)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -currentdatefont
+#
+# Specifies the font used for the current date text.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::currentdatefont {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure now \
+ -font $itk_option(-currentdatefont)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -dayfont
+#
+# Specifies the font used for the day of the week text.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::dayfont {
+ if {$_initialized} {
+ $itk_component(page) itemconfigure days \
+ -font $itk_option(-dayfont)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -startday
+#
+# Specifies the starting day for the week. The value must be a day of the
+# week: sunday, monday, tuesday, wednesday, thursday, friday, or
+# saturday. The default is sunday.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Calendar::startday {
+ set day [string tolower $itk_option(-startday)]
+
+ switch $day {
+ sunday {set _offset 0}
+ monday {set _offset 1}
+ tuesday {set _offset 2}
+ wednesday {set _offset 3}
+ thursday {set _offset 4}
+ friday {set _offset 5}
+ saturday {set _offset 6}
+ default {
+ error "bad startday option \"$itk_option(-startday)\":\
+ should be sunday, monday, tuesday, wednesday,\
+ thursday, friday, or saturday"
+ }
+ }
+
+ if {$_initialized} {
+ $itk_component(page) delete all-page
+ _redraw
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: get ?format?
+#
+# Returns the currently selected date in one of two formats, string
+# or as an integer clock value using the -string and -clicks
+# options respectively. The default is by string. Reference the
+# clock command for more information on obtaining dates and their
+# formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::get {{format "-string"}} {
+ switch -- $format {
+ "-string" {
+ return $_selected
+ }
+ "-clicks" {
+ return [clock scan $_selected]
+ }
+ default {
+ error "bad format option \"$format\":\
+ should be -string or -clicks"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: select date_
+#
+# Changes the currently selected date to the value specified.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::select {{date_ "now"}} {
+ if {$date_ == "now"} {
+ set time [clock seconds]
+ } else {
+ if {[catch {clock format $date_}] == 0} {
+ set time $date_
+ } elseif {[catch {set time [clock scan $date_]}] != 0} {
+ error "bad date: \"$date_\", must be a valid date string, clock clicks value or the keyword now"
+ }
+ }
+ switch $itk_option(-int) {
+ yes { set _format "%Y-%m-%d" }
+ no { set _format "%m/%d/%Y" }
+ }
+ _select [clock format $time -format "$_format"]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: show date_
+#
+# Changes the currently display month to be that of the specified
+# date.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::show {{date_ "now"}} {
+ if {$date_ == "now"} {
+ set _time [clock seconds]
+ } else {
+ if {[catch {clock format $date_}] == 0} {
+ set _time $date_
+ } elseif {[catch {set _time [clock scan $date_]}] != 0} {
+ error "bad date: \"$date_\", must be a valid date string, clock clicks value or the keyword now"
+ }
+ }
+
+ $itk_component(page) delete all-page
+ _redraw
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _drawtext canvas_ day_ date_ now_
+# x0_ y0_ x1_ y1_
+#
+# Draws the text in the date square. The method is protected such that
+# it can be overridden in derived classes that may wish to add their
+# own unique text. The method receives the day to draw along with
+# the coordinates of the square.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_drawtext {canvas_ day_ date_ now_ x0_ y0_ x1_ y1_} {
+ set item [$canvas_ create text \
+ [expr {(($x1_ - $x0_) / 2) + $x0_}] \
+ [expr {(($y1_ -$y0_) / 2) + $y0_ + 1}] \
+ -anchor center -text "$day_" \
+ -fill $itk_option(-foreground)]
+
+ if {$date_ == $now_} {
+ $canvas_ itemconfigure $item \
+ -font $itk_option(-currentdatefont) \
+ -tags [list all-page date text now]
+ } else {
+ $canvas_ itemconfigure $item \
+ -font $itk_option(-datefont) \
+ -tags [list all-page date text]
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _configureHandler
+#
+# Processes a configure event received on the canvas. The method
+# deletes all the current canvas items and forces a redraw.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_configureHandler {} {
+ set _initialized 1
+
+ $itk_component(page) delete all
+ _redraw
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _change delta_
+#
+# Changes the current month displayed in the calendar, moving
+# forward or backward by <delta_> months where <delta_> is +/-
+# some number.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_change {delta_} {
+ set dir [expr {($delta_ > 0) ? 1 : -1}]
+ set month [clock format $_time -format "%m"]
+ set month [string trimleft $month 0]
+ set year [clock format $_time -format "%Y"]
+
+ for {set i 0} {$i < abs($delta_)} {incr i} {
+ incr month $dir
+ if {$month < 1} {
+ set month 12
+ incr year -1
+ } elseif {$month > 12} {
+ set month 1
+ incr year 1
+ }
+ }
+ if {[catch {set _time [clock scan "$month/1/$year"]}]} {
+ bell
+ } else {
+ _redraw
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _redraw
+#
+# Redraws the calendar. This method is invoked whenever the
+# calendar changes size or we need to effect a change such as draw
+# it with a new month.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_redraw {} {
+ #
+ # Set the format based on the option -int
+ #
+ switch $itk_option(-int) {
+ yes { set _format "%Y-%m-%d" }
+ no { set _format "%m/%d/%Y" }
+ }
+ #
+ # Remove all the items that typically change per redraw request
+ # such as the title and dates. Also, get the maximum width and
+ # height of the page.
+ #
+ $itk_component(page) delete all-page
+
+ set wmax [winfo width $itk_component(page)]
+ set hmax [winfo height $itk_component(page)]
+
+ #
+ # If we haven't yet created the forward and backwards buttons,
+ # then dot it; otherwise, skip it.
+ #
+ if {[$itk_component(page) find withtag button] == {}} {
+ $itk_component(page) create window 3 3 -anchor nw \
+ -window $itk_component(backward) -tags button
+ $itk_component(page) create window [expr {$wmax-3}] 3 -anchor ne \
+ -window $itk_component(forward) -tags button
+ }
+
+ #
+ # Create the title centered between the buttons.
+ #
+ foreach {x0 y0 x1 y1} [$itk_component(page) bbox button] {
+ set x [expr {(($x1-$x0)/2)+$x0}]
+ set y [expr {(($y1-$y0)/2)+$y0}]
+ }
+
+ set title [clock format $_time -format "%B %Y"]
+ $itk_component(page) create text $x $y -anchor center \
+ -text $title -font $itk_option(-titlefont) \
+ -fill $itk_option(-foreground) \
+ -tags [list title text all-page]
+
+ #
+ # Add the days of the week labels if they haven't yet been created.
+ #
+ if {[$itk_component(page) find withtag days] == {}} {
+ _days $wmax
+ }
+
+ #
+ # Add a line between the calendar header and the dates if needed.
+ #
+ set bottom [expr {[lindex [$itk_component(page) bbox all] 3] + 3}]
+
+ if {[$itk_component(page) find withtag line] == {}} {
+ $itk_component(page) create line 0 $bottom $wmax $bottom \
+ -width 2 -tags line
+ }
+
+ incr bottom 3
+
+ #
+ # Get the layout for the time value and create the date squares.
+ # This includes the surrounding date rectangle, the date text,
+ # and the sensor. Bind selection to the sensor.
+ #
+ set current ""
+ set now [clock format [clock seconds] -format "$_format"]
+
+ set layout [_layout $_time]
+ set weeks [expr {[lindex $layout end] + 1}]
+
+ foreach {day date kind dcol wrow} $layout {
+ set x0 [expr {$dcol*($wmax-7)/7+3}]
+ set y0 [expr {$wrow*($hmax-$bottom-4)/$weeks+$bottom}]
+ set x1 [expr {($dcol+1)*($wmax-7)/7+3}]
+ set y1 [expr {($wrow+1)*($hmax-$bottom-4)/$weeks+$bottom}]
+
+ if {$date == $_selected} {
+ set current $date
+ }
+
+ #
+ # Create the rectangle that surrounds the date and configure
+ # its background based on the wheather it is a weekday or
+ # a weekend.
+ #
+ set item [$itk_component(page) create rectangle $x0 $y0 $x1 $y1 \
+ -outline $itk_option(-outline)]
+
+ if {$kind == "weekend"} {
+ $itk_component(page) itemconfigure $item \
+ -fill $itk_option(-weekendbackground) \
+ -tags [list all-page square weekend]
+ } else {
+ $itk_component(page) itemconfigure $item \
+ -fill $itk_option(-weekdaybackground) \
+ -tags [list all-page square weekday]
+ }
+
+ #
+ # Create the date text and configure its font based on the
+ # wheather or not it is the current date.
+ #
+ _drawtext $itk_component(page) $day $date $now $x0 $y0 $x1 $y1
+
+ #
+ # Create a sensor area to detect selections. Bind the
+ # sensor and pass the date to the bind script.
+ #
+ $itk_component(page) create rectangle $x0 $y0 $x1 $y1 \
+ -outline "" -fill "" \
+ -tags [list $date-sensor all-sensor all-page]
+
+ $itk_component(page) bind $date-sensor <ButtonPress-1> \
+ [itcl::code $this _selectEvent $date]
+ }
+
+ #
+ # Highlight the selected date if it is on this page.
+ #
+ if {$current != ""} {
+ $itk_component(page) itemconfigure $current-sensor \
+ -outline $itk_option(-selectcolor) \
+ -width $itk_option(-selectthickness)
+
+ $itk_component(page) raise $current-sensor
+
+ } elseif {$_selected == ""} {
+ set date [clock format $_time -format "$_format"]
+ _select $date
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _days
+#
+# Used to rewite the days of the week label just below the month
+# title string. The days are given in the -days option.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_days {{wmax {}}} {
+ if {$wmax == {}} {
+ set wmax [winfo width $itk_component(page)]
+ }
+
+ set col 0
+ set bottom [expr {[lindex [$itk_component(page) bbox title buttons] 3] + 7}]
+
+ foreach dayoweek $itk_option(-days) {
+ set x0 [expr {$col*($wmax/7)}]
+ set x1 [expr {($col+1)*($wmax/7)}]
+
+ $itk_component(page) create text \
+ [expr {(($x1 - $x0) / 2) + $x0}] $bottom \
+ -anchor n -text "$dayoweek" \
+ -fill $itk_option(-foreground) \
+ -font $itk_option(-dayfont) \
+ -tags [list days text]
+
+ incr col
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _layout time_
+#
+# Used whenever the calendar is redrawn. Finds the month containing
+# a <time_> in seconds, and returns a list for all of the days in
+# that month. The list looks like this:
+#
+# {day1 date1 kind1 c1 r1 day2 date2 kind2 c2 r2 ...}
+#
+# where dayN is a day number like 1,2,3,..., dateN is the date for
+# dayN, kindN is the day type of weekday or weekend, and cN,rN
+# are the column/row indices for the square containing that date.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_layout {time_} {
+
+ switch $itk_option(-int) {
+ yes { set _format "%Y-%m-%d" }
+ no { set _format "%m/%d/%Y" }
+ }
+
+ set month [clock format $time_ -format "%m"]
+ set year [clock format $time_ -format "%Y"]
+
+ foreach lastday {31 30 29 28} {
+ if {[catch {clock scan "$month/$lastday/$year"}] == 0} {
+ break
+ }
+ }
+ set seconds [clock scan "$month/1/$year"]
+ set firstday [_adjustday [clock format $seconds -format %w]]
+
+ set weeks [expr {ceil(double($lastday+$firstday)/7)}]
+
+ set rlist ""
+ for {set day 1} {$day <= $lastday} {incr day} {
+ set seconds [clock scan "$month/$day/$year"]
+ set date [clock format $seconds -format "$_format"]
+ set dayoweek [clock format $seconds -format %w]
+
+ if {$dayoweek == 0 || $dayoweek == 6} {
+ set kind "weekend"
+ } else {
+ set kind "weekday"
+ }
+
+ set daycol [_adjustday $dayoweek]
+
+ set weekrow [expr {($firstday+$day-1)/7}]
+ lappend rlist $day $date $kind $daycol $weekrow
+ }
+ return $rlist
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _adjustday day_
+#
+# Modifies the day to be in accordance with the startday option.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_adjustday {day_} {
+ set retday [expr {$day_ - $_offset}]
+
+ if {$retday < 0} {
+ set retday [expr {$retday + 7}]
+ }
+
+ return $retday
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _select date_
+#
+# Selects the current <date_> on the calendar. Highlights the date
+# on the calendar, and executes the command associated with the
+# calendar, with the selected date substituted in place of "%d".
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_select {date_} {
+
+ switch $itk_option(-int) {
+ yes { set _format "%Y-%m-%d" }
+ no { set _format "%m/%d/%Y" }
+ }
+
+
+ set time [clock scan $date_]
+ set date [clock format $time -format "$_format"]
+
+ set _selected $date
+ set current [clock format $_time -format "%m %Y"]
+ set selected [clock format $time -format "%m %Y"]
+
+ if {$current == $selected} {
+ $itk_component(page) itemconfigure all-sensor \
+ -outline "" -width 1
+
+ $itk_component(page) itemconfigure $date-sensor \
+ -outline $itk_option(-selectcolor) \
+ -width $itk_option(-selectthickness)
+ $itk_component(page) raise $date-sensor
+ } else {
+ set _time $time
+ _redraw
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _selectEvent date_
+#
+# Selects the current <date_> on the calendar. Highlights the date
+# on the calendar, and executes the command associated with the
+# calendar, with the selected date substituted in place of "%d".
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_selectEvent {date_} {
+ _select $date_
+
+ if {[string trim $itk_option(-command)] != ""} {
+ set cmd $itk_option(-command)
+ set cmd [_percentSubst %d $cmd [get]]
+ uplevel #0 $cmd
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _percentSubst pattern_ string_ subst_
+#
+# This command is a "safe" version of regsub, for substituting
+# each occurance of <%pattern_> in <string_> with <subst_>. The
+# usual Tcl "regsub" command does the same thing, but also
+# converts characters like "&" and "\0", "\1", etc. that may
+# be present in the <subst_> string.
+#
+# Returns <string_> with <subst_> substituted in place of each
+# <%pattern_>.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Calendar::_percentSubst {pattern_ string_ subst_} {
+ if {![string match %* $pattern_]} {
+ error "bad pattern \"$pattern_\": should be %something"
+ }
+
+ set rval ""
+ while {[regexp "(.*)${pattern_}(.*)" $string_ all head tail]} {
+ set rval "$subst_$tail$rval"
+ set string_ $head
+ }
+ set rval "$string_$rval"
+}
diff --git a/iwidgets/generic/canvasprintbox.itk b/iwidgets/generic/canvasprintbox.itk
new file mode 100644
index 00000000000..9d41daae25d
--- /dev/null
+++ b/iwidgets/generic/canvasprintbox.itk
@@ -0,0 +1,1111 @@
+#
+# CanvasPrintBox v1.5
+# ----------------------------------------------------------------------
+# Implements a print box for printing the contents of a canvas widget
+# to a printer or a file. It is possible to specify page orientation, the
+# number of pages to print the image on and if the output should be
+# stretched to fit the page.
+#
+# CanvasPrintBox is a "super-widget" that can be used as an
+# element in ones own GUIs. It is used to print the contents
+# of a canvas (called the source hereafter) to a printer or a
+# file. Possible settings include: portrait and landscape orientation
+# of the output, stretching the output to fit the page while maintaining
+# a proper aspect-ratio and posterizing to enlarge the output to fit on
+# multiple pages. A stamp-sized copy of the source will be shown (called
+# the stamp hereafter) at all times to reflect the effect of changing
+# the settings will have on the output.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Tako Schotanus EMAIL: Tako.Schotanus@bouw.tno.nl
+# ----------------------------------------------------------------------
+# Copyright (c) 1995 Tako Schotanus
+# ======================================================================
+# Permission is hereby granted, without written agreement and without
+# license or royalty fees, to use, copy, modify, and distribute this
+# software and its documentation for any purpose, provided that the
+# above copyright notice and the following two paragraphs appear in
+# all copies of this software.
+#
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+# ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+# IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+# THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+# ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Canvasprintbox.filename "canvas.ps" widgetDefault
+option add *Canvasprintbox.hPageCnt 1 widgetDefault
+option add *Canvasprintbox.orient landscape widgetDefault
+option add *Canvasprintbox.output printer widgetDefault
+option add *Canvasprintbox.pageSize A4 widgetDefault
+option add *Canvasprintbox.posterize 0 widgetDefault
+option add *Canvasprintbox.printCmd lpr widgetDefault
+option add *Canvasprintbox.printRegion "" widgetDefault
+option add *Canvasprintbox.vPageCnt 1 widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Canvasprintbox {
+ keep -background -cursor -textbackground -foreground
+}
+
+#<
+#
+# CanvasPrintBox is a "super-widget" that can be used as an
+# element in ones own GUIs. It is used to print the contents
+# of a canvas (called the source hereafter) to a printer or a
+# file. Possible settings include: portrait and landscape orientation
+# of the output, stretching the output to fit the page while maintaining
+# a proper aspect-ratio and posterizing to enlarge the output to fit on
+# multiple pages. A stamp-sized copy of the source will be shown (called
+# the stamp hereafter) at all times to reflect the effect of changing
+# the settings will have on the output.
+#
+#>
+itcl::class iwidgets::Canvasprintbox {
+ inherit itk::Widget
+
+ #
+ # Holds the current state for all check- and radiobuttons.
+ #
+ itk_option define -filename filename FileName "canvas.ps"
+ itk_option define -hpagecnt hPageCnt PageCnt 1
+ itk_option define -orient orient Orient "landscape"
+ itk_option define -output output Output "printer"
+ itk_option define -pagesize pageSize PageSize "A4"
+ itk_option define -posterize posterize Posterize 0
+ itk_option define -printcmd printCmd PrintCmd ""
+ itk_option define -printregion printRegion PrintRegion ""
+ itk_option define -stretch stretch Stretch 0
+ itk_option define -vpagecnt vPageCnt PageCnt 1
+
+ constructor {args} {}
+ destructor {}
+
+ # ---------------------------------------------------------------
+ # PUBLIC
+ #----------------------------------------------------------------
+ public {
+ method getoutput {}
+ method print {}
+ method refresh {}
+ method setcanvas {canv}
+ method stop {}
+ }
+
+ # ---------------------------------------------------------------
+ # PROTECTED
+ #----------------------------------------------------------------
+ protected {
+ #
+ # Just holds the names of some widgets/objects. "win" is used to
+ # determine if the object is fully constructed and initialized.
+ #
+ variable win ""
+ variable canvw ""
+
+ #
+ # The canvas we want to print.
+ #
+ variable canvas ""
+
+ #
+ # Boolean indicating if the attribute "orient" is set
+ # to landscape or not.
+ #
+ variable rotate 1
+
+ #
+ # Holds the configure options that were used to create this object.
+ #
+ variable init_opts ""
+
+ #
+ # The following attributes hold a list of lines that are
+ # currently drawn on the "stamp" to show how the page(s) is/are
+ # oriented. The first holds the vertical dividing lines and the
+ # second the horizontal ones.
+ #
+ variable hlines ""
+ variable vlines ""
+
+ #
+ # Updating is set when the thumbnail is being drawn. Settings
+ # this to 0 while drawing is still busy will terminate the
+ # proces.
+ # Restart_update can be set to 1 when the thumbnail is being
+ # drawn to force a redraw.
+ #
+ variable _reposition ""
+ variable _update_attr_id ""
+
+ method _calc_poster_size {}
+ method _calc_print_region {}
+ method _calc_print_scale {}
+ method _mapEventHandler {}
+ method _update_attr {{when later}}
+ method _update_canvas {{when later}}
+
+ common _globVar
+
+ proc ezPaperInfo {size {attr ""} \
+ {orient "portrait"} {window ""}} {}
+ }
+}
+
+#
+# Provide a lowercased access method for the Canvasprintbox class.
+#
+proc ::iwidgets::canvasprintbox {args} {
+ uplevel ::iwidgets::Canvasprintbox $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+#<
+# A list of four coordinates specifying which part of the canvas to print.
+# An empty list means that the canvas' entire scrollregion should be
+# printed. Any change to this attribute will automatically update the "stamp".
+# Defaults to an empty list.
+#>
+itcl::configbody iwidgets::Canvasprintbox::printregion {
+ if {$itk_option(-printregion) != ""
+ && [llength $itk_option(-printregion)] != 4} {
+ error {bad option "printregion": should contain 4 coordinates}
+ }
+ _update_canvas
+}
+
+#<
+# Specifies where the postscript output should go: to the printer
+# or to a file. Can take on the values "printer" or "file".
+# The corresponding entry-widget will reflect the contents of
+# either the printcmd attribute or the filename attribute.
+#>
+itcl::configbody iwidgets::Canvasprintbox::output {
+ switch $itk_option(-output) {
+ file - printer {
+ set _globVar($this,output) $itk_option(-output)
+ }
+ default {
+ error {bad output option \"$itk_option(-output)\":\
+ should be file or printer}
+ }
+ }
+ _update_attr
+}
+
+#<
+# The command to execute when printing the postscript output.
+# The command will get the postscript directed to its standard
+# input. (Only when output is set to "printer")
+#>
+itcl::configbody iwidgets::Canvasprintbox::printcmd {
+ set _globVar($this,printeref) $itk_option(-printcmd)
+ _update_attr
+}
+
+#<
+# The file to write the postscript output to (Only when output
+# is set to "file"). If posterizing is turned on and hpagecnt
+# and/or vpagecnt is more than 1, x.y is appended to the filename
+# where x is the horizontal page number and y the vertical page number.
+#>
+itcl::configbody iwidgets::Canvasprintbox::filename {
+ set _globVar($this,fileef) $itk_option(-filename)
+ _update_attr
+}
+
+#<
+# The pagesize the printer supports. Changes to this attribute
+# will be reflected immediately in the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::pagesize {
+ set opt [string tolower $itk_option(-pagesize)]
+ set lst [string tolower [ezPaperInfo types]]
+ if {[lsearch $lst $opt] == -1} {
+ error "bad option \"pagesize\": should be one of: [ezPaperInfo types]"
+ }
+ $itk_component(paperom) select "*[string range $opt 1 end]"
+ _update_canvas
+}
+
+#<
+# Determines the orientation of the output to the printer (or file).
+# It can take the value "portrait" or "landscape" (default). Changes
+# to this attribute will be reflected immediately in the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::orient {
+ switch $itk_option(-orient) {
+ "portrait" - "landscape" {
+ $itk_component(orientom) select $itk_option(-orient)
+ _update_canvas
+
+ }
+ default {
+ error "bad orient option \"$itk_option(-orient)\":\
+ should be portrait or landscape"
+ }
+ }
+}
+
+#<
+# Determines if the output should be stretched to fill the
+# page (as defined by the attribute pagesize) as large as
+# possible. The aspect-ratio of the output will be retained
+# and the output will never fall outside of the boundaries
+# of the page.
+#>
+itcl::configbody iwidgets::Canvasprintbox::stretch {
+ if {$itk_option(-stretch) != 0 && $itk_option(-stretch) != 1} {
+ error {bad option "stretch": should be a boolean}
+ }
+ set _globVar($this,stretchcb) $itk_option(-stretch)
+ _update_attr
+}
+
+#<
+# Indicates if posterizing is turned on or not. Posterizing
+# the output means that it is possible to distribute the
+# output over more than one page. This way it is possible to
+# print a canvas/region which is larger than the specified
+# pagesize without stretching. If used in combination with
+# stretching it can be used to "blow up" the contents of a
+# canvas to as large as size as you want (See attributes:
+# hpagecnt end vpagecnt). Any change to this attribute will
+# automatically update the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::posterize {
+ if {$itk_option(-posterize) != "0" && $itk_option(-posterize) != "1"} {
+ error "expected boolean but got \"$itk_option(-posterize)\""
+ }
+ set _globVar($this,postercb) $itk_option(-posterize)
+ _update_canvas
+}
+
+#<
+# Is used in combination with "posterize" to determine over
+# how many pages the output should be distributed. This
+# attribute specifies how many pages should be used horizontaly.
+# Any change to this attribute will automatically update the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::hpagecnt {
+ set _globVar($this,hpc) $itk_option(-hpagecnt)
+ _update_canvas
+}
+
+#<
+# Is used in combination with "posterize" to determine over
+# how many pages the output should be distributed. This
+# attribute specifies how many pages should be used verticaly.
+# Any change to this attribute will automatically update the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::vpagecnt {
+ set _globVar($this,vpc) $itk_option(-vpagecnt)
+ _update_canvas
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Canvasprintbox::constructor {args} {
+ set _globVar($this,output) printer
+ set _globVar($this,printeref) ""
+ set _globVar($this,fileef) "canvas.ps"
+ set _globVar($this,hpc) 1
+ set _globVar($this,vpc) 1
+ set _globVar($this,postercb) 0
+ set _globVar($this,stretchcb) 0
+
+ itk_component add canvasframe {
+ frame $itk_interior.f18 -bd 2
+ }
+
+ itk_component add canvas {
+ canvas $itk_component(canvasframe).c1 \
+ -bd 2 -relief sunken \
+ -scrollregion {0c 0c 10c 10c} \
+ -width 250
+ }
+ pack $itk_component(canvas) -expand 1 -fill both
+
+ itk_component add outputom {
+ iwidgets::Labeledframe $itk_interior.outputom \
+ -labelpos nw \
+ -labeltext "Output to"
+ }
+ set cs [$itk_component(outputom) childsite]
+
+ itk_component add printerrb {
+ radiobutton $cs.printerrb \
+ -text Printer \
+ -variable [itcl::scope _globVar($this,output)] \
+ -anchor w \
+ -justify left \
+ -value printer \
+ -command [itcl::code $this _update_attr]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+ itk_component add printeref {
+ iwidgets::entryfield $cs.printeref \
+ -labeltext "command:" \
+ -state normal \
+ -labelpos w \
+ -textvariable [itcl::scope _globVar($this,printeref)]
+ }
+
+ itk_component add filerb {
+ radiobutton $cs.filerb \
+ -text File \
+ -justify left \
+ -anchor w \
+ -variable [itcl::scope _globVar($this,output)] \
+ -value file \
+ -command [itcl::code $this _update_attr]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+ itk_component add fileef {
+ iwidgets::entryfield $cs.fileef \
+ -labeltext "filename:" \
+ -state disabled \
+ -labelpos w \
+ -textvariable [itcl::scope _globVar($this,fileef)]
+ }
+
+ itk_component add propsframe {
+ iwidgets::Labeledframe $itk_interior.propsframe \
+ -labelpos nw \
+ -labeltext "Properties"
+ }
+ set cs [$itk_component(propsframe) childsite]
+
+ itk_component add paperom {
+ iwidgets::optionmenu $cs.paperom \
+ -labelpos w -cyclicon 1 \
+ -labeltext "Paper size:" \
+ -command [itcl::code $this refresh]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+ eval $itk_component(paperom) insert end [ezPaperInfo types]
+ $itk_component(paperom) select A4
+
+ itk_component add orientom {
+ iwidgets::radiobox $itk_interior.orientom \
+ -labeltext "Orientation" -command [itcl::code $this refresh]
+ }
+ $itk_component(orientom) add landscape -text Landscape
+ $itk_component(orientom) add portrait -text Portrait
+ $itk_component(orientom) select 0
+
+ itk_component add stretchcb {
+ checkbutton $cs.stretchcb \
+ -relief flat \
+ -text {Stretch to fit} \
+ -justify left \
+ -anchor w \
+ -variable [itcl::scope _globVar($this,stretchcb)] \
+ -command [itcl::code $this refresh]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ itk_component add postercb {
+ checkbutton $cs.postercb \
+ -relief flat \
+ -text Posterize \
+ -justify left \
+ -anchor w \
+ -variable [itcl::scope _globVar($this,postercb)] \
+ -command [itcl::code $this refresh]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ itk_component add hpcnt {
+ iwidgets::entryfield $cs.hpcnt \
+ -labeltext on \
+ -textvariable [itcl::scope _globVar($this,hpc)] \
+ -validate integer -width 3 \
+ -command [itcl::code $this refresh]
+ }
+
+ itk_component add vpcnt {
+ iwidgets::entryfield $cs.vpcnt \
+ -labeltext by \
+ -textvariable [itcl::scope _globVar($this,vpc)] \
+ -validate integer -width 3 \
+ -command [itcl::code $this refresh]
+ }
+
+ itk_component add pages {
+ label $cs.pages -text pages.
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ set init_opts $args
+
+ grid $itk_component(canvasframe) -row 0 -column 0 -rowspan 4 -sticky nsew
+ grid $itk_component(propsframe) -row 0 -column 1 -sticky nsew
+ grid $itk_component(outputom) -row 1 -column 1 -sticky nsew
+ grid $itk_component(orientom) -row 2 -column 1 -sticky nsew
+ grid columnconfigure $itk_interior 0 -weight 1
+ grid rowconfigure $itk_interior 3 -weight 1
+
+ grid $itk_component(printerrb) -row 0 -column 0 -sticky nsw
+ grid $itk_component(printeref) -row 0 -column 1 -sticky nsw
+ grid $itk_component(filerb) -row 1 -column 0 -sticky nsw
+ grid $itk_component(fileef) -row 1 -column 1 -sticky nsw
+ iwidgets::Labeledwidget::alignlabels $itk_component(printeref) $itk_component(fileef)
+ grid columnconfigure $itk_component(outputom) 1 -weight 1
+
+ grid $itk_component(paperom) -row 0 -column 0 -columnspan 2 -sticky nsw
+ grid $itk_component(stretchcb) -row 1 -column 0 -sticky nsw
+ grid $itk_component(postercb) -row 2 -column 0 -sticky nsw
+ grid $itk_component(hpcnt) -row 2 -column 1 -sticky nsw
+ grid $itk_component(vpcnt) -row 2 -column 2 -sticky nsw
+ grid $itk_component(pages) -row 2 -column 3 -sticky nsw
+ grid columnconfigure $itk_component(propsframe) 3 -weight 1
+
+ eval itk_initialize $args
+
+ bind $itk_component(pages) <Map> +[itcl::code $this _mapEventHandler]
+ bind $itk_component(canvas) <Configure> +[itcl::code $this refresh]
+}
+
+
+# ---------------------------------------------------------------
+# PUBLIC METHODS
+#----------------------------------------------------------------
+
+#<
+# This is used to set the canvas that has to be printed.
+# A stamp-sized copy will automatically be drawn to show how the
+# output would look with the current settings.
+#
+# In: canv - The canvas to be printed
+# Out: canvas (attrib) - Holds the canvas to be printed
+#>
+itcl::body iwidgets::Canvasprintbox::setcanvas {canv} {
+ set canvas $canv
+ _update_canvas
+}
+
+#<
+# Returns the value of the -printercmd or -filename option
+# depending on the current setting of -output.
+#
+# In: itk_option (attrib)
+# Out: The value of -printercmd or -filename
+#>
+itcl::body iwidgets::Canvasprintbox::getoutput {} {
+ switch $_globVar($this,output) {
+ "file" {
+ return $_globVar($this,fileef)
+ }
+ "printer" {
+ return $_globVar($this,printeref)
+ }
+ }
+ return ""
+}
+
+#<
+# Perfrom the actual printing of the canvas using the current settings of
+# all the attributes.
+#
+# In: itk_option, rotate (attrib)
+# Out: A boolean indicating wether printing was successful
+#>
+itcl::body iwidgets::Canvasprintbox::print {} {
+
+ global env tcl_platform
+
+ stop
+
+ if {$itk_option(-output) == "file"} {
+ set nm $_globVar($this,fileef)
+ if {[string range $nm 0 1] == "~/"} {
+ set nm "$env(HOME)/[string range $nm 2 end]"
+ }
+ } else {
+ set nm "/tmp/xge[winfo id $canvas]"
+ }
+
+ set pr [_calc_print_region]
+ set x1 [lindex $pr 0]
+ set y1 [lindex $pr 1]
+ set x2 [lindex $pr 2]
+ set y2 [lindex $pr 3]
+ set cx [expr {int(($x2 + $x1) / 2)}]
+ set cy [expr {int(($y2 + $y1) / 2)}]
+ if {!$itk_option(-stretch)} {
+ set ps [_calc_poster_size]
+ set pshw [expr {int([lindex $ps 0] / 2)}]
+ set pshh [expr {int([lindex $ps 1] / 2)}]
+ set x [expr {$cx - $pshw}]
+ set y [expr {$cy - $pshh}]
+ set w [ezPaperInfo $itk_option(-pagesize) pwidth $itk_option(-orient) $win]
+ set h [ezPaperInfo $itk_option(-pagesize) pheight $itk_option(-orient) $win]
+ } else {
+ set x $x1
+ set y $y1
+ set w [expr {($x2-$x1) / $_globVar($this,hpc)}]
+ set h [expr {($y2-$y1) / $_globVar($this,vpc)}]
+ }
+
+ set i 0
+ set px $x
+ while {$i < $_globVar($this,hpc)} {
+ set j 0
+ set py $y
+ while {$j < $_globVar($this,vpc)} {
+ set nm2 [expr {$_globVar($this,hpc) > 1 || $_globVar($this,vpc) > 1 ? "$nm$i.$j" : $nm}]
+
+ if {$itk_option(-stretch)} {
+ $canvas postscript \
+ -file $nm2 \
+ -rotate $rotate \
+ -x $px -y $py \
+ -width $w \
+ -height $h \
+ -pagex [ezPaperInfo $itk_option(-pagesize) centerx] \
+ -pagey [ezPaperInfo $itk_option(-pagesize) centery] \
+ -pagewidth [ezPaperInfo $itk_option(-pagesize) pwidth $itk_option(-orient)] \
+ -pageheight [ezPaperInfo $itk_option(-pagesize) pheight $itk_option(-orient)]
+ } else {
+ $canvas postscript \
+ -file $nm2 \
+ -rotate $rotate \
+ -x $px -y $py \
+ -width $w \
+ -height $h \
+ -pagex [ezPaperInfo $itk_option(-pagesize) centerx] \
+ -pagey [ezPaperInfo $itk_option(-pagesize) centery]
+ }
+
+ if {$itk_option(-output) == "printer"} {
+ set cmd "$itk_option(-printcmd) < $nm2"
+ if {[catch {eval exec $cmd &}]} {
+ return 0
+ }
+ }
+
+ set py [expr {$py + $h}]
+ incr j
+ }
+ set px [expr {$px + $w}]
+ incr i
+ }
+
+ return 1
+}
+
+#<
+# Retrieves the current value for all edit fields and updates
+# the stamp accordingly. Is useful for Apply-buttons.
+#>
+itcl::body iwidgets::Canvasprintbox::refresh {} {
+ stop
+ _update_canvas
+ return
+}
+
+#<
+# Stops the drawing of the "stamp". I'm currently unable to detect
+# when a Canvasprintbox gets withdrawn. It's therefore advised
+# that you perform a stop before you do something like that.
+#>
+itcl::body iwidgets::Canvasprintbox::stop {} {
+
+ if {$_reposition != ""} {
+ after cancel $_reposition
+ set _reposition ""
+ }
+
+ if {$_update_attr_id != ""} {
+ after cancel $_update_attr_id
+ set _update_attr_id ""
+ }
+
+ return
+}
+
+# ---------------------------------------------------------------
+# PROTECTED METHODS
+#----------------------------------------------------------------
+
+#
+# Calculate the total size the output would be with the current
+# settings for "pagesize" and "posterize" (and "hpagecnt" and
+# "vpagecnt"). This size will be the size of the printable area,
+# some space has been substracted to take into account that a
+# page should have borders because most printers can't print on
+# the very edge of the paper.
+#
+# In: posterize, hpagecnt, vpagecnt, pagesize, orient (attrib)
+# Out: A list of two numbers indicating the width and the height
+# of the total paper area which will be used for printing
+# in pixels.
+#
+itcl::body iwidgets::Canvasprintbox::_calc_poster_size {} {
+ set tpw [expr {[ezPaperInfo $itk_option(-pagesize) \
+ pwidth $itk_option(-orient) $win]*$_globVar($this,hpc)}]
+ set tph [expr {[ezPaperInfo $itk_option(-pagesize) \
+ pheight $itk_option(-orient) $win]*$_globVar($this,vpc)}]
+
+ return "$tpw $tph"
+}
+
+#
+# Determine which area of the "source" canvas will be printed.
+# If "printregion" was set by the "user" this will be used and
+# converted to pixel-coordinates. If the user didn't set it
+# the bounding box that contains all canvas-items will be used
+# instead.
+#
+# In: printregion, canvas (attrib)
+# Out: Four floats specifying the region to be printed in
+# pixel-coordinates (topleft & bottomright).
+#
+itcl::body iwidgets::Canvasprintbox::_calc_print_region {} {
+ set printreg [expr {$itk_option(-printregion) != ""
+ ? $itk_option(-printregion) : [$canvas bbox all]}]
+
+ if {$printreg != ""} {
+ set prx1 [winfo fpixels $canvas [lindex $printreg 0]]
+ set pry1 [winfo fpixels $canvas [lindex $printreg 1]]
+ set prx2 [winfo fpixels $canvas [lindex $printreg 2]]
+ set pry2 [winfo fpixels $canvas [lindex $printreg 3]]
+
+ set res "$prx1 $pry1 $prx2 $pry2"
+ } else {
+ set res "0 0 0 0"
+ }
+
+ return $res
+}
+
+#
+# Calculate the scaling factor needed if the output was
+# to be stretched to fit exactly on the page (or pages).
+# If stretching is turned off this will always return 1.0.
+#
+# In: stretch (attrib)
+# Out: A float specifying the scaling factor.
+#
+itcl::body iwidgets::Canvasprintbox::_calc_print_scale {} {
+ if {$itk_option(-stretch)} {
+ set pr [_calc_print_region]
+ set prw [expr {[lindex $pr 2] - [lindex $pr 0]}]
+ set prh [expr {[lindex $pr 3] - [lindex $pr 1]}]
+ set ps [_calc_poster_size]
+ set psw [lindex $ps 0]
+ set psh [lindex $ps 1]
+ set sfx [expr {$psw / $prw}]
+ set sfy [expr {$psh / $prh}]
+ set sf [expr {$sfx < $sfy ? $sfx : $sfy}]
+ return $sf
+ } else {
+ return 1.0
+ }
+}
+
+#
+# Schedule the thread that makes a copy of the "source"
+# canvas to the "stamp".
+#
+# In: win, canvas (attrib)
+# Out: -
+#
+itcl::body iwidgets::Canvasprintbox::_update_canvas {{when later}} {
+ if {$win == "" || $canvas == "" || [$canvas find all] == ""} {
+ return
+ }
+ if {$when == "later"} {
+ if {$_reposition == ""} {
+ set _reposition [after idle [itcl::code $this _update_canvas now]]
+ }
+ return
+ }
+
+ _update_attr now
+
+ #
+ # Make a copy of the "source" canvas to the "stamp".
+ #
+ if {$_globVar($this,hpc) == [llength $vlines] &&
+ $_globVar($this,vpc) == [llength $hlines]} {
+ stop
+ return
+ }
+
+ $canvw delete all
+
+ set width [winfo width $canvw]
+ set height [winfo height $canvw]
+ set ps [_calc_poster_size]
+
+ #
+ # Calculate the scaling factor that would be needed to fit the
+ # whole "source" into the "stamp". This takes into account the
+ # total amount of "paper" that would be needed to print the
+ # contents of the "source".
+ #
+ set xsf [expr {$width/[lindex $ps 0]}]
+ set ysf [expr {$height/[lindex $ps 1]}]
+ set sf [expr {$xsf < $ysf ? $xsf : $ysf}]
+ set w [expr {[lindex $ps 0]*$sf}]
+ set h [expr {[lindex $ps 1]*$sf}]
+ set x1 [expr {($width-$w)/2}]
+ set y1 [expr {($height-$h)/2}]
+ set x2 [expr {$x1+$w}]
+ set y2 [expr {$y1+$h}]
+ set cx [expr {($x2+$x1)/ 2}]
+ set cy [expr {($y2+$y1)/ 2}]
+
+ set printreg [_calc_print_region]
+ set prx1 [lindex $printreg 0]
+ set pry1 [lindex $printreg 1]
+ set prx2 [lindex $printreg 2]
+ set pry2 [lindex $printreg 3]
+ set prcx [expr {($prx2+$prx1)/2}]
+ set prcy [expr {($pry2+$pry1)/2}]
+
+ set psf [_calc_print_scale]
+
+ #
+ # Copy all items from the "real" canvas to the canvas
+ # showing what we'll send to the printer. Bitmaps and
+ # texts are not copied because they can't be scaled,
+ # a rectangle will be created instead.
+ #
+ set tsf [expr {$sf * $psf}]
+ set dx [expr {$cx-($prcx*$tsf)}]
+ set dy [expr {$cy-($prcy*$tsf)}]
+ $canvw create rectangle \
+ [expr {$x1+0}] \
+ [expr {$y1+0}] \
+ [expr {$x2-0}] \
+ [expr {$y2-0}] -fill white
+ set items [eval "$canvas find overlapping $printreg"]
+
+ set itemCount [llength $items]
+ for {set cnt 0} {$cnt < $itemCount} {incr cnt} {
+ #
+ # Determine the item's type and coordinates
+ #
+ set i [lindex $items $cnt]
+ set t [$canvas type $i]
+ set crds [$canvas coords $i]
+
+ #
+ # Ask for the item's configuration settings and strip
+ # it to leave only a list of option names and values.
+ #
+ set cfg [$canvas itemconfigure $i]
+ set cfg2 ""
+ foreach c $cfg {
+ if {[llength $c] == 5} {
+ lappend cfg2 [lindex $c 0] [lindex $c 4]
+ }
+ }
+
+ #
+ # Handle texts and bitmaps differently: they will
+ # be represented as rectangles.
+ #
+ if {$t == "text" || $t == "bitmap" || $t == "window"} {
+ set t "rectangle"
+ set crds [$canvas bbox $i]
+ set cfg2 "-outline {} -fill gray"
+ }
+
+ #
+ # Remove the arrows from a line item when the scale
+ # factor drops below 1/3rd of the original size.
+ # This to prevent the arrowheads from dominating the
+ # display.
+ #
+ if {$t == "line" && $tsf < 0.33} {
+ lappend cfg2 -arrow none
+ }
+
+ #
+ # Create a copy of the item on the "printing" canvas.
+ #
+ set i2 [eval "$canvw create $t $crds $cfg2"]
+ $canvw scale $i2 0 0 $tsf $tsf
+ $canvw move $i2 $dx $dy
+
+ if {($cnt%25) == 0} {
+ update
+ }
+ if {$_reposition == ""} {
+ return
+ }
+ }
+
+ set p $x1
+ set i 1
+ set vlines {}
+ while {$i < $_globVar($this,hpc)} {
+ set p [expr {$p + ($w/$_globVar($this,hpc))}]
+ set l [$canvw create line $p $y1 $p $y2]
+ lappend vlines $l
+ incr i
+ }
+
+ set p $y1
+ set i 1
+ set vlines {}
+ while {$i < $_globVar($this,vpc)} {
+ set p [expr {$p + ($h/$_globVar($this,vpc))}]
+ set l [$canvw create line $x1 $p $x2 $p]
+ lappend vlines $l
+ incr i
+ }
+
+ set _reposition ""
+}
+
+#
+# Update the attributes to reflect changes made in the user-
+# interface.
+#
+# In: itk_option (attrib) - the attributes to update
+# itk_component (attrib) - the widgets
+# _globVar (common) - the global var holding the state
+# of all radiobuttons and checkboxes.
+# Out: -
+#
+itcl::body iwidgets::Canvasprintbox::_update_attr {{when "later"}} {
+ if {$when != "now"} {
+ if {$_update_attr_id == ""} {
+ set _update_attr_id [after idle [itcl::code $this _update_attr now]]
+ }
+ return
+ }
+
+ set itk_option(-printcmd) $_globVar($this,printeref)
+ set itk_option(-filename) $_globVar($this,fileef)
+ set itk_option(-output) $_globVar($this,output)
+ set itk_option(-pagesize) [string tolower [$itk_component(paperom) get]]
+ set itk_option(-stretch) $_globVar($this,stretchcb)
+ set itk_option(-posterize) $_globVar($this,postercb)
+ set itk_option(-vpagecnt) $_globVar($this,vpc)
+ set itk_option(-hpagecnt) $_globVar($this,hpc)
+ set itk_option(-orient) [$itk_component(orientom) get]
+ set rotate [expr {$itk_option(-orient) == "landscape"}]
+
+ if {$_globVar($this,output) == "file"} {
+ $itk_component(fileef) configure \
+ -state normal -foreground $itk_option(-foreground)
+ $itk_component(printeref) configure \
+ -state disabled -foreground $itk_option(-disabledforeground)
+ } else {
+ $itk_component(fileef) configure \
+ -state disabled -foreground $itk_option(-disabledforeground)
+ $itk_component(printeref) configure \
+ -state normal -foreground $itk_option(-foreground)
+ }
+
+ set fg [expr {$_globVar($this,postercb) \
+ ? $itk_option(-foreground) : $itk_option(-disabledforeground)}]
+
+ $itk_component(vpcnt) configure -foreground $fg
+ $itk_component(hpcnt) configure -foreground $fg
+ $itk_component(pages) configure -foreground $fg
+
+ #
+ # Update dependencies among widgets. (For example: disabling
+ # an entry-widget when its associated checkbox-button is used
+ # to turn of the option (the entry's value is not needed
+ # anymore and this should be reflected in the fact that it
+ # isn't possible to change it anymore).
+ #
+ # former method:_update_widgets/_update_UI
+ #
+ set state [expr {$itk_option(-posterize) ? "normal" : "disabled"}]
+ $itk_component(vpcnt) configure -state $state
+ $itk_component(hpcnt) configure -state $state
+ $itk_component(paperom) select "*[string range $itk_option(-pagesize) 1 end]"
+
+ set _update_attr_id ""
+}
+
+#
+# Gets called when the CanvasPrintBox-widget gets mapped.
+#
+itcl::body iwidgets::Canvasprintbox::_mapEventHandler {} {
+ set win $itk_interior
+ set canvw $itk_component(canvas)
+ if {$canvas != ""} {
+ setcanvas $canvas
+ }
+ _update_attr
+}
+
+#
+# Destroy this object and its associated widgets.
+#
+itcl::body iwidgets::Canvasprintbox::destructor {} {
+ stop
+}
+
+#
+# Hold the information about common paper sizes. A bit of a hack, but it
+# should be possible to add your own if you take a look at it.
+#
+itcl::body iwidgets::Canvasprintbox::ezPaperInfo {size {attr ""} \
+ {orient "portrait"} {window ""}} {
+
+ set size [string tolower $size]
+ set attr [string tolower $attr]
+ set orient [string tolower $orient]
+
+ case $size in {
+ types {
+ return "A5 A4 A3 A2 A1 Legal Letter"
+ }
+ a5 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "13.85c"
+ set paper(y2) "20.0c"
+ set paper(pheight) "19.0c"
+ set paper(pwidth) "12.85c"
+ set paper(height) "21.0c"
+ set paper(width) "14.85c"
+ set paper(centerx) "7.425c"
+ set paper(centery) "10.5c"
+ }
+ a4 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "20.0c"
+ set paper(y2) "28.7c"
+ set paper(pheight) "27.7c"
+ set paper(pwidth) "19.0c"
+ set paper(height) "29.7c"
+ set paper(width) "21.0c"
+ set paper(centerx) "10.5c"
+ set paper(centery) "14.85c"
+ }
+ a3 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "28.7c"
+ set paper(y2) "41.0c"
+ set paper(pheight) "40.0c"
+ set paper(pwidth) "27.7c"
+ set paper(height) "42.0c"
+ set paper(width) "29.7c"
+ set paper(centerx) "14.85c"
+ set paper(centery) "21.0c"
+ }
+ a2 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "41.0c"
+ set paper(y2) "58.4c"
+ set paper(pheight) "57.4c"
+ set paper(pwidth) "40.0c"
+ set paper(height) "59.4c"
+ set paper(width) "42.0c"
+ set paper(centerx) "21.0c"
+ set paper(centery) "29.7c"
+ }
+ a1 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "58.4c"
+ set paper(y2) "83.0c"
+ set paper(pheight) "82.0c"
+ set paper(pwidth) "57.4c"
+ set paper(height) "84.0c"
+ set paper(width) "59.4c"
+ set paper(centerx) "29.7c"
+ set paper(centery) "42.0c"
+ }
+ legal {
+ set paper(x1) "0.2i"
+ set paper(y1) "0.2i"
+ set paper(x2) "8.3i"
+ set paper(y2) "13.8i"
+ set paper(pheight) "13.6i"
+ set paper(pwidth) "8.1i"
+ set paper(height) "14.0i"
+ set paper(width) "8.5i"
+ set paper(centerx) "4.25i"
+ set paper(centery) "7.0i"
+ }
+ letter {
+ set paper(x1) "0.2i"
+ set paper(y1) "0.2i"
+ set paper(x2) "8.3i"
+ set paper(y2) "10.8i"
+ set paper(pheight) "10.6i"
+ set paper(pwidth) "8.1i"
+ set paper(height) "11.0i"
+ set paper(width) "8.5i"
+ set paper(centerx) "4.25i"
+ set paper(centery) "5.5i"
+ }
+ default {
+ error "ezPaperInfo: Unknown paper type ($type)"
+ }
+ }
+
+ set inv(x1) "y1"
+ set inv(x2) "y2"
+ set inv(y1) "x1"
+ set inv(y2) "x2"
+ set inv(pwidth) "pheight"
+ set inv(pheight) "pwidth"
+ set inv(width) "height"
+ set inv(height) "width"
+ set inv(centerx) "centery"
+ set inv(centery) "centerx"
+
+ case $orient in {
+ landscape {
+ set res $paper($inv($attr))
+ }
+ portrait {
+ set res $paper($attr)
+ }
+ default {
+ error "ezPaperInfo: orientation should be\
+ portrait or landscape (not $orient)"
+ }
+ }
+
+ if {$window != ""} {
+ set res [winfo fpixels $window $res]
+ }
+
+ return $res
+}
diff --git a/iwidgets/generic/canvasprintdialog.itk b/iwidgets/generic/canvasprintdialog.itk
new file mode 100644
index 00000000000..ddd14cfc1a6
--- /dev/null
+++ b/iwidgets/generic/canvasprintdialog.itk
@@ -0,0 +1,155 @@
+#
+# CanvasPrintDialog v1.5
+# ----------------------------------------------------------------------
+# Implements a print dialog for printing the contents of a canvas widget
+# to a printer or a file. It is possible to specify page orientation, the
+# number of pages to print the image on and if the output should be
+# stretched to fit the page. The CanvasPrintDialog is derived from the
+# Dialog class and is composed of a CanvasPrintBox with attributes set to
+# manipulate the dialog buttons.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Tako Schotanus EMAIL: Tako.Schotanus@bouw.tno.nl
+# ----------------------------------------------------------------------
+# Copyright (c) 1995 Tako Schotanus
+# ======================================================================
+# Permission is hereby granted, without written agreement and without
+# license or royalty fees, to use, copy, modify, and distribute this
+# software and its documentation for any purpose, provided that the
+# above copyright notice and the following two paragraphs appear in
+# all copies of this software.
+#
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+# ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+# IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+# THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+# ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# ======================================================================
+
+#
+# Option database default resources:
+#
+option add *Canvasprintdialog.filename "canvas.ps" widgetDefault
+option add *Canvasprintdialog.hPageCnt 1 widgetDefault
+option add *Canvasprintdialog.orient landscape widgetDefault
+option add *Canvasprintdialog.output printer widgetDefault
+option add *Canvasprintdialog.pageSize A4 widgetDefault
+option add *Canvasprintdialog.posterize 0 widgetDefault
+option add *Canvasprintdialog.printCmd lpr widgetDefault
+option add *Canvasprintdialog.printRegion "" widgetDefault
+option add *Canvasprintdialog.vPageCnt 1 widgetDefault
+option add *Canvasprintdialog.title "Canvas Print Dialog" widgetDefault
+option add *Canvasprintdialog.master "." widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Canvasprintdialog {
+ keep -background -cursor -foreground -modality
+}
+
+# ------------------------------------------------------------------
+# CANVASPRINTDIALOG
+# ------------------------------------------------------------------
+itcl::class iwidgets::Canvasprintdialog {
+ inherit iwidgets::Dialog
+
+ constructor {args} {}
+ destructor {}
+
+ method deactivate {args} {}
+ method getoutput {} {}
+ method setcanvas {canv} {}
+ method refresh {} {}
+ method print {} {}
+}
+
+#
+# Provide a lowercased access method for the Canvasprintdialog class.
+#
+proc ::iwidgets::canvasprintdialog {args} {
+ uplevel ::iwidgets::Canvasprintdialog $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+#
+# Create new file selection dialog.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Canvasprintdialog::constructor {args} {
+ component hull configure -borderwidth 0
+
+ #
+ # Instantiate a file selection box widget.
+ #
+ itk_component add cpb {
+ iwidgets::Canvasprintbox $itk_interior.cpb
+ } {
+ usual
+ keep -printregion -output -printcmd -filename -pagesize \
+ -orient -stretch -posterize -hpagecnt -vpagecnt
+ }
+ pack $itk_component(cpb) -fill both -expand yes
+
+ #
+ # Hide the apply and help buttons.
+ #
+ buttonconfigure OK -text Print
+ buttonconfigure Apply -command [itcl::code $this refresh] -text Refresh
+ hide Help
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: deactivate
+#
+# Redefines method of dialog shell class. Stops the drawing of the
+# thumbnail (when busy) upon deactivation of the dialog.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Canvasprintdialog::deactivate {args} {
+ $itk_component(cpb) stop
+ return [eval Shell::deactivate $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: getoutput
+#
+# Thinwrapped method of canvas print box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Canvasprintdialog::getoutput {} {
+ return [$itk_component(cpb) getoutput]
+}
+
+# ------------------------------------------------------------------
+# METHOD: setcanvas
+#
+# Thinwrapped method of canvas print box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Canvasprintdialog::setcanvas {canv} {
+ return [$itk_component(cpb) setcanvas $canv]
+}
+
+# ------------------------------------------------------------------
+# METHOD: refresh
+#
+# Thinwrapped method of canvas print box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Canvasprintdialog::refresh {} {
+ return [$itk_component(cpb) refresh]
+}
+
+# ------------------------------------------------------------------
+# METHOD: print
+#
+# Thinwrapped method of canvas print box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Canvasprintdialog::print {} {
+ return [$itk_component(cpb) print]
+}
diff --git a/iwidgets/generic/checkbox.itk b/iwidgets/generic/checkbox.itk
new file mode 100644
index 00000000000..49e88887f76
--- /dev/null
+++ b/iwidgets/generic/checkbox.itk
@@ -0,0 +1,341 @@
+#
+# Checkbox
+# ----------------------------------------------------------------------
+# Implements a checkbuttonbox. Supports adding, inserting, deleting,
+# selecting, and deselecting of checkbuttons by tag and index.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: John A. Tucker EMAIL: jatucker@spd.dsccc.com
+#
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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.
+# ======================================================================
+
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Checkbox.labelMargin 10 widgetDefault
+option add *Checkbox.labelFont \
+ "-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*" widgetDefault
+option add *Checkbox.labelPos nw widgetDefault
+option add *Checkbox.borderWidth 2 widgetDefault
+option add *Checkbox.relief groove widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Checkbox {
+ keep -background -borderwidth -cursor -foreground -labelfont
+}
+
+# ------------------------------------------------------------------
+# CHECKBOX
+# ------------------------------------------------------------------
+itcl::class iwidgets::Checkbox {
+ inherit iwidgets::Labeledframe
+
+ constructor {args} {}
+
+ itk_option define -orient orient Orient vertical
+
+ public {
+ method add {tag args}
+ method insert {index tag args}
+ method delete {index}
+ method get {{index ""}}
+ method index {index}
+ method select {index}
+ method deselect {index}
+ method flash {index}
+ method toggle {index}
+ method buttonconfigure {index args}
+ }
+
+ private {
+
+ method gettag {index} ;# Get the tag of the checkbutton associated
+ ;# with a numeric index
+
+ variable _unique 0 ;# Unique id for choice creation.
+ variable _buttons {} ;# List of checkbutton tags.
+ common buttonVar ;# Array of checkbutton "-variables"
+ }
+}
+
+#
+# Provide a lowercased access method for the Checkbox class.
+#
+proc ::iwidgets::checkbox {pathName args} {
+ uplevel ::iwidgets::Checkbox $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::constructor {args} {
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -orient
+#
+# Allows the user to orient the checkbuttons either horizontally
+# or vertically. Added by Chad Smith (csmith@adc.com) 3/10/00.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Checkbox::orient {
+ if {$itk_option(-orient) == "horizontal"} {
+ foreach tag $_buttons {
+ pack $itk_component($tag) -side left -anchor nw -padx 4 -expand 1
+ }
+ } elseif {$itk_option(-orient) == "vertical"} {
+ foreach tag $_buttons {
+ pack $itk_component($tag) -side top -anchor w -padx 4 -expand 0
+ }
+ } else {
+ error "Bad orientation: $itk_option(-orient). Should be\
+ \"horizontal\" or \"vertical\"."
+ }
+}
+
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: index index
+#
+# Searches the checkbutton tags in the checkbox for the one with the
+# requested tag, numerical index, or keyword "end". Returns the
+# choices's numerical index if found, otherwise error.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::index {index} {
+ if {[llength $_buttons] > 0} {
+ if {[regexp {(^[0-9]+$)} $index]} {
+ if {$index < [llength $_buttons]} {
+ return $index
+ } else {
+ error "Checkbox index \"$index\" is out of range"
+ }
+
+ } elseif {$index == "end"} {
+ return [expr {[llength $_buttons] - 1}]
+
+ } else {
+ if {[set idx [lsearch $_buttons $index]] != -1} {
+ return $idx
+ }
+
+ error "bad Checkbox index \"$index\": must be number, end,\
+ or pattern"
+ }
+
+ } else {
+ error "Checkbox \"$itk_component(hull)\" has no checkbuttons"
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: add tag ?option value option value ...?
+#
+# Add a new tagged checkbutton to the checkbox at the end. The method
+# takes additional options which are passed on to the checkbutton
+# constructor. These include most of the typical checkbutton
+# options. The tag is returned.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::add {tag args} {
+ itk_component add $tag {
+ eval checkbutton $itk_component(childsite).cb[incr _unique] \
+ -variable [list [itcl::scope buttonVar($this,$tag)]] \
+ -anchor w \
+ -justify left \
+ -highlightthickness 0 \
+ $args
+ } {
+ usual
+ keep -command -disabledforeground -selectcolor -state
+ ignore -highlightthickness -highlightcolor
+ rename -font -labelfont labelFont Font
+ }
+
+ # Redraw the buttons with the proper orientation.
+ if {$itk_option(-orient) == "vertical"} {
+ pack $itk_component($tag) -side top -anchor w -padx 4 -expand 0
+ } else {
+ pack $itk_component($tag) -side left -anchor nw -expand 1
+ }
+
+ lappend _buttons $tag
+
+ return $tag
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert index tag ?option value option value ...?
+#
+# Insert the tagged checkbutton in the checkbox just before the
+# one given by index. Any additional options are passed on to the
+# checkbutton constructor. These include the typical checkbutton
+# options. The tag is returned.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::insert {index tag args} {
+ itk_component add $tag {
+ eval checkbutton $itk_component(childsite).cb[incr _unique] \
+ -variable [list [itcl::scope buttonVar($this,$tag)]] \
+ -anchor w \
+ -justify left \
+ -highlightthickness 0 \
+ $args
+ } {
+ usual
+ ignore -highlightthickness -highlightcolor
+ rename -font -labelfont labelFont Font
+ }
+
+ set index [index $index]
+ set before [lindex $_buttons $index]
+ set _buttons [linsert $_buttons $index $tag]
+
+ pack $itk_component($tag) -anchor w -padx 4 -before $itk_component($before)
+
+ return $tag
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete index
+#
+# Delete the specified checkbutton.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::delete {index} {
+
+ set tag [gettag $index]
+ set index [index $index]
+ destroy $itk_component($tag)
+ set _buttons [lreplace $_buttons $index $index]
+
+ if { [info exists buttonVar($this,$tag)] == 1 } {
+ unset buttonVar($this,$tag)
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: select index
+#
+# Select the specified checkbutton.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::select {index} {
+ set tag [gettag $index]
+ #-----------------------------------------------------------
+ # BUG FIX: csmith (Chad Smith: csmith@adc.com), 3/30/99
+ #-----------------------------------------------------------
+ # This method should only invoke the checkbutton if it's not
+ # already selected. Check its associated variable, and if
+ # it's set, then just ignore and return.
+ #-----------------------------------------------------------
+ if {[set [itcl::scope buttonVar($this,$tag)]] ==
+ [[component $tag] cget -onvalue]} {
+ return
+ }
+ $itk_component($tag) invoke
+}
+
+# ------------------------------------------------------------------
+# METHOD: toggle index
+#
+# Toggle a specified checkbutton between selected and unselected
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::toggle {index} {
+ set tag [gettag $index]
+ $itk_component($tag) toggle
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Return the value of the checkbutton with the given index, or a
+# list of all checkbutton values in increasing order by index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::get {{index ""}} {
+ set result {}
+
+ if {$index == ""} {
+ foreach tag $_buttons {
+ if {$buttonVar($this,$tag)} {
+ lappend result $tag
+ }
+ }
+ } else {
+ set tag [gettag $index]
+ set result $buttonVar($this,$tag)
+ }
+
+ return $result
+}
+
+# ------------------------------------------------------------------
+# METHOD: deselect index
+#
+# Deselect the specified checkbutton.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::deselect {index} {
+ set tag [gettag $index]
+ $itk_component($tag) deselect
+}
+
+# ------------------------------------------------------------------
+# METHOD: flash index
+#
+# Flash the specified checkbutton.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::flash {index} {
+ set tag [gettag $index]
+ $itk_component($tag) flash
+}
+
+# ------------------------------------------------------------------
+# METHOD: buttonconfigure index ?option? ?value option value ...?
+#
+# Configure a specified checkbutton. This method allows configuration
+# of checkbuttons from the Checkbox level. The options may have any
+# of the values accepted by the add method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::buttonconfigure {index args} {
+ set tag [gettag $index]
+ eval $itk_component($tag) configure $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: gettag index
+#
+# Return the tag of the checkbutton associated with a specified
+# numeric index
+# ------------------------------------------------------------------
+itcl::body iwidgets::Checkbox::gettag {index} {
+ return [lindex $_buttons [index $index]]
+}
diff --git a/iwidgets/generic/colors.itcl b/iwidgets/generic/colors.itcl
new file mode 100644
index 00000000000..948819d7a81
--- /dev/null
+++ b/iwidgets/generic/colors.itcl
@@ -0,0 +1,209 @@
+#
+# colors
+# ----------------------------------------------------------------------
+# The colors class encapsulates several color related utility functions.
+# Class level scope resolution must be used inorder to access the static
+# member functions.
+#
+# USAGE:
+# set hsb [colors::rgbToHsb [winfo rgb . bisque]]
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1995 Mark L. Ulferts
+# ======================================================================
+# Permission is hereby granted, without written agreement and without
+# license or royalty fees, to use, copy, modify, and distribute this
+# software and its documentation for any purpose, provided that the
+# above copyright notice and the following two paragraphs appear in
+# all copies of this software.
+#
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+# ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+# IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+# THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+# ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# ======================================================================
+
+namespace eval iwidgets::colors {
+
+ # ------------------------------------------------------------------
+ # PROCEDURE: rgbToNumeric
+ #
+ # Returns the numeric value for a list of red, green, and blue.
+ # ------------------------------------------------------------------
+ proc rgbToNumeric {rgb} {
+ if {[llength $rgb] != 3} {
+ error "bad arg: \"$rgb\", should be list of red, green, and blue"
+ }
+
+ return [format "#%04x%04x%04x" \
+ [lindex $rgb 0] [lindex $rgb 1] [lindex $rgb 2]]
+ }
+
+ # ------------------------------------------------------------------
+ # PROCEDURE: rgbToHsb
+ #
+ # The procedure below converts an RGB value to HSB. It takes red,
+ # green, and blue components (0-65535) as arguments, and returns a
+ # list containing HSB components (floating-point, 0-1) as result.
+ # The code here is a copy of the code on page 615 of "Fundamentals
+ # of Interactive Computer Graphics" by Foley and Van Dam.
+ # ------------------------------------------------------------------
+ proc rgbToHsb {rgb} {
+ if {[llength $rgb] != 3} {
+ error "bad arg: \"$rgb\", should be list of red, green, and blue"
+ }
+
+ set r [expr {[lindex $rgb 0]/65535.0}]
+ set g [expr {[lindex $rgb 1]/65535.0}]
+ set b [expr {[lindex $rgb 2]/65535.0}]
+
+ set max 0
+ if {$r > $max} {set max $r}
+ if {$g > $max} {set max $g}
+ if {$b > $max} {set max $b}
+
+ set min 65535
+ if {$r < $min} {set min $r}
+ if {$g < $min} {set min $g}
+ if {$b < $min} {set min $b}
+
+ if {$max != 0} {
+ set sat [expr {($max-$min)/$max}]
+ } else {
+ set sat 0
+ }
+ if {$sat == 0} {
+ set hue 0
+ } else {
+ set rc [expr {($max-$r)/($max-$min)}]
+ set gc [expr {($max-$g)/($max-$min)}]
+ set bc [expr {($max-$b)/($max-$min)}]
+
+ if {$r == $max} {
+ set hue [expr {$bc-$gc}]
+ } elseif {$g == $max} {
+ set hue [expr {2+$rc-$bc}]
+ } elseif {$b == $max} {
+ set hue [expr {4+$gc-$rc}]
+ }
+ set hue [expr {$hue*0.1666667}]
+ if {$hue < 0} {set hue [expr {$hue+1.0}]}
+ }
+ return [list $hue $sat $max]
+ }
+
+ # ------------------------------------------------------------------
+ # PROCEDURE: hsbToRgb
+ #
+ # The procedure below converts an HSB value to RGB. It takes hue,
+ # saturation, and value components (floating-point, 0-1.0) as
+ # arguments, and returns a list containing RGB components (integers,
+ # 0-65535) as result. The code here is a copy of the code on page
+ # 616 of "Fundamentals of Interactive Computer Graphics" by Foley
+ # and Van Dam.
+ # ------------------------------------------------------------------
+ proc hsbToRgb {hsb} {
+
+ if {[llength $hsb] != 3} {
+ error "bad arg: \"$hsb\", should be list of hue, saturation, and brightness"
+ }
+
+ set hue [lindex $hsb 0]
+ set sat [lindex $hsb 1]
+ set value [lindex $hsb 2]
+
+ set v [format %.0f [expr {65535.0*$value}]]
+ if {$sat == 0} {
+ return "$v $v $v"
+ } else {
+ set hue [expr {$hue*6.0}]
+ if {$hue >= 6.0} {
+ set hue 0.0
+ }
+ scan $hue. %d i
+ set f [expr {$hue-$i}]
+ set p [format %.0f [expr {65535.0*$value*(1 - $sat)}]]
+ set q [format %.0f [expr {65535.0*$value*(1 - ($sat*$f))}]]
+ set t [format %.0f [expr {65535.0*$value*(1 - ($sat*(1 - $f)))}]]
+ case $i \
+ 0 {return "$v $t $p"} \
+ 1 {return "$q $v $p"} \
+ 2 {return "$p $v $t"} \
+ 3 {return "$p $q $v"} \
+ 4 {return "$t $p $v"} \
+ 5 {return "$v $p $q"}
+ error "i value $i is out of range"
+ }
+ }
+
+ # ------------------------------------------------------------------
+ #
+ # PROCEDURE: topShadow bgColor
+ #
+ # This method computes a lighter shadow variant of bgColor.
+ # It wants to decrease the saturation to 25%. But if there is
+ # no saturation (as in gray colors) it tries to turn the
+ # brightness up by 10%. It maxes the brightness at 1.0 to
+ # avoid bogus colors...
+ #
+ # bgColor is converted to HSB where the calculations are
+ # made. Then converted back to an rgb color number (hex fmt)
+ #
+ # ------------------------------------------------------------------
+ proc topShadow { bgColor } {
+
+ set hsb [rgbToHsb [winfo rgb . $bgColor]]
+
+ set saturation [lindex $hsb 1]
+ set brightness [lindex $hsb 2]
+
+ if { $brightness < 0.9 } {
+ # try turning the brightness up first.
+ set brightness [expr {$brightness * 1.1}]
+ } else {
+ # otherwise fiddle with saturation
+ set saturation [expr {$saturation * 0.25}]
+ }
+
+ set hsb [lreplace $hsb 1 1 [set saturation]]
+ set hsb [lreplace $hsb 2 2 [set brightness]]
+
+ set rgb [hsbToRgb $hsb]
+ set color [rgbToNumeric $rgb]
+ return $color
+ }
+
+
+ # ------------------------------------------------------------------
+ #
+ # PROC: bottomShadow bgColor
+ #
+ #
+ # This method computes a darker shadow variant of bg color.
+ # It takes the brightness and decreases it to 80% of its
+ # original value.
+ #
+ # bgColor is converted to HSB where the calculations are
+ # made. Then converted back to an rgb color number (hex fmt)
+ #
+ # ------------------------------------------------------------------
+ proc bottomShadow { bgColor } {
+
+ set hsb [rgbToHsb [winfo rgb . $bgColor]]
+ set hsb [lreplace $hsb 2 2 [expr {[lindex $hsb 2] * 0.8}]]
+ set rgb [hsbToRgb $hsb]
+ set color [rgbToNumeric $rgb]
+ return $color
+ }
+}
diff --git a/iwidgets/generic/combobox.itk b/iwidgets/generic/combobox.itk
new file mode 100644
index 00000000000..5b38157c1c7
--- /dev/null
+++ b/iwidgets/generic/combobox.itk
@@ -0,0 +1,1443 @@
+# Combobox
+# ----------------------------------------------------------------------
+# Implements a Combobox widget. A Combobox has 2 basic styles: simple and
+# dropdown. Dropdowns display an entry field with an arrow button to the
+# right of it. When the arrow button is pressed a selectable list of
+# items is popped up. A simple Combobox displays an entry field and a listbox
+# just beneath it which is always displayed. In both types, if the user
+# selects an item in the listbox, the contents of the entry field are
+# replaced with the text from the selected item. If the Combobox is
+# editable, the user can type in the entry field and when <Return> is
+# pressed the item will be inserted into the list.
+#
+# WISH LIST:
+# This section lists possible future enhancements.
+#
+# Combobox 1.x:
+# - convert bindings to bindtags.
+#
+# ----------------------------------------------------------------------
+# ORIGINAL AUTHOR: John S. Sigler
+# ----------------------------------------------------------------------
+# CURRENT MAINTAINER: Chad Smith EMAIL: csmith@adc.com, itclguy@yahoo.com
+#
+# Copyright (c) 1995 John S. Sigler
+# Copyright (c) 1997 Mitch Gorman
+# ======================================================================
+# Permission is hereby granted, without written agreement and without
+# license or royalty fees, to use, copy, modify, and distribute this
+# software and its documentation for any purpose, provided that the
+# above copyright notice and the following two paragraphs appear in
+# all copies of this software.
+#
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+# ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+# IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+# THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+# ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Combobox.borderWidth 2 widgetDefault
+option add *Combobox.labelPos wn widgetDefault
+option add *Combobox.listHeight 150 widgetDefault
+option add *Combobox.hscrollMode dynamic widgetDefault
+option add *Combobox.vscrollMode dynamic widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Combobox {
+ keep -background -borderwidth -cursor -foreground -highlightcolor \
+ -highlightthickness -insertbackground -insertborderwidth \
+ -insertofftime -insertontime -insertwidth -labelfont -popupcursor \
+ -selectbackground -selectborderwidth -selectforeground \
+ -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# COMBOBOX
+# ------------------------------------------------------------------
+itcl::class iwidgets::Combobox {
+ inherit iwidgets::Entryfield
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -arrowrelief arrowRelief Relief raised
+ itk_option define -completion completion Completion true
+ itk_option define -dropdown dropdown Dropdown true
+ itk_option define -editable editable Editable true
+ itk_option define -grab grab Grab local
+ itk_option define -listheight listHeight Height 150
+ itk_option define -margin margin Margin 1
+ itk_option define -popupcursor popupCursor Cursor arrow
+ itk_option define -selectioncommand selectionCommand SelectionCommand {}
+ itk_option define -state state State normal
+ itk_option define -unique unique Unique true
+
+ public method clear {{component all}}
+ public method curselection {}
+ public method delete {component first {last {}}}
+ public method get {{index {}}}
+ public method getcurselection {}
+ public method insert {component index args}
+ public method invoke {}
+ public method justify {direction}
+ public method see {index}
+ public method selection {option first {last {}}}
+ public method size {}
+ public method sort {{mode ascending}}
+ public method xview {args}
+ public method yview {args}
+
+ protected method _addToList {}
+ protected method _createComponents {}
+ protected method _deleteList {first {last {}}}
+ protected method _deleteText {first {last {}}}
+ protected method _doLayout {{when later}}
+ protected method _drawArrow {}
+ protected method _dropdownBtnRelease {{window {}} {x 1} {y 1}}
+ protected method _ignoreNextBtnRelease {ignore}
+ protected method _next {}
+ protected method _packComponents {{when later}}
+ protected method _positionList {}
+ protected method _postList {}
+ protected method _previous {}
+ protected method _resizeArrow {}
+ protected method _selectCmd {}
+ protected method _toggleList {}
+ protected method _unpostList {}
+ protected method _commonBindings {}
+ protected method _dropdownBindings {}
+ protected method _simpleBindings {}
+ protected method _listShowing {{val ""}}
+
+ private method _bs {}
+ private method _lookup {key}
+ private method _slbListbox {}
+ private method _stateSelect {}
+
+ private variable _doit 0;
+ private variable _inbs 0;
+ private variable _inlookup 0;
+ private variable _currItem {}; ;# current selected item.
+ private variable _ignoreRelease false ;# next button release ignored.
+ private variable _isPosted false; ;# is the dropdown popped up.
+ private variable _repacking {} ;# non-null => _packComponents pending.
+ private variable _grab ;# used to restore grabs
+ private variable _next_prevFLAG 0 ;# Used in _lookup to fix SF Bug 501300
+ private common _listShowing
+ private common count 0
+}
+
+#
+# Provide a lowercase access method for the Combobox class.
+#
+proc ::iwidgets::combobox {pathName args} {
+ uplevel ::iwidgets::Combobox $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Combobox::constructor {args} {
+ set _listShowing($this) 0
+ set _grab(window) ""
+ set _grab(status) ""
+
+ # combobox is different as all components are created
+ # after determining what the dropdown style is...
+
+ # configure args
+ eval itk_initialize $args
+
+ # create components that are dependent on options
+ # (Scrolledlistbox, arrow button) and pack them.
+ if {$count == 0} {
+ image create bitmap downarrow -data {
+ #define down_width 16
+ #define down_height 16
+ static unsigned char down_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0xf8, 0x3f,
+ 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ }
+ image create bitmap uparrow -data {
+ #define up_width 16
+ #define up_height 16
+ static unsigned char up_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f,
+ 0xfc, 0x1f, 0xfe, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ }
+ }
+ incr count
+ _doLayout
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Combobox::destructor {} {
+ # catch any repacking that may be waiting for idle time
+ if {$_repacking != ""} {
+ after cancel $_repacking
+ }
+ incr count -1
+ if {$count == 0} {
+ image delete uparrow
+ image delete downarrow
+ }
+}
+
+# ================================================================
+# OPTIONS
+# ================================================================
+
+# --------------------------------------------------------------------
+# OPTION: -arrowrelief
+#
+# Relief style used on the arrow button.
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::arrowrelief {}
+
+# --------------------------------------------------------------------
+# OPTION: -completion
+#
+# Relief style used on the arrow button.
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::completion {
+ switch -- $itk_option(-completion) {
+ 0 - no - false - off { }
+ 1 - yes - true - on { }
+ default {
+ error "bad completion option \"$itk_option(-completion)\":\
+ should be boolean"
+ }
+ }
+}
+
+# --------------------------------------------------------------------
+# OPTION: -dropdown
+#
+# Boolean which determines the Combobox style: dropdown or simple.
+# Because the two style's lists reside in different toplevel widgets
+# this is more complicated than it should be.
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::dropdown {
+ switch -- $itk_option(-dropdown) {
+ 1 - yes - true - on {
+ if {[winfo exists $itk_interior.list]} {
+ set vals [$itk_component(list) get 0 end]
+ destroy $itk_component(list)
+ _doLayout
+ if [llength $vals] {
+ eval insert list end $vals
+ }
+ }
+ }
+ 0 - no - false - off {
+ if {[winfo exists $itk_interior.popup.list]} {
+ set vals [$itk_component(list) get 0 end]
+ catch {destroy $itk_component(arrowBtn)}
+ destroy $itk_component(popup) ;# this deletes the list too
+ _doLayout
+ if [llength $vals] {
+ eval insert list end $vals
+ }
+ }
+ }
+ default {
+ error "bad dropdown option \"$itk_option(-dropdown)\":\
+ should be boolean"
+ }
+ }
+}
+
+# --------------------------------------------------------------------
+# OPTION: -editable
+#
+# Boolean which allows/disallows user input to the entry field area.
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::editable {
+ switch -- $itk_option(-editable) {
+ 1 - true - yes - on {
+ switch -- $itk_option(-state) {
+ normal {
+ $itk_component(entry) configure -state normal
+ }
+ }
+ }
+ 0 - false - no - off {
+ $itk_component(entry) configure -state disabled
+ }
+ default {
+ error "bad editable option \"$itk_option(-editable)\":\
+ should be boolean"
+ }
+ }
+}
+
+# --------------------------------------------------------------------
+# OPTION: -grab
+#
+# grab-state of megawidget
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::grab {
+ switch -- $itk_option(-grab) {
+ local { }
+ global { }
+ default {
+ error "bad grab value \"$itk_option(-grab)\":\
+ must be global or local"
+ }
+ }
+}
+
+# --------------------------------------------------------------------
+# OPTION: -listheight
+#
+# Listbox height in pixels. (Need to integrate the scrolledlistbox
+# -visibleitems option here - at least for simple listbox.)
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::listheight {}
+
+# --------------------------------------------------------------------
+# OPTION: -margin
+#
+# Spacer between the entry field and arrow button of dropdown style
+# Comboboxes.
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::margin {
+ grid columnconfigure $itk_interior 0 -minsize $itk_option(-margin)
+}
+
+# --------------------------------------------------------------------
+# OPTION: -popupcursor
+#
+# Set the cursor for the popup list.
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::popupcursor {}
+
+# --------------------------------------------------------------------
+# OPTION: -selectioncommand
+#
+# Defines the proc to be called when an item is selected in the list.
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::selectioncommand {}
+
+# --------------------------------------------------------------------
+# OPTION: -state
+#
+# overall state of megawidget
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::state {
+ switch -- $itk_option(-state) {
+ disabled {
+ $itk_component(entry) configure -state disabled
+ }
+ normal {
+ switch -- $itk_option(-editable) {
+ 1 - true - yes - on {
+ $itk_component(entry) configure -state normal
+ }
+ 0 - false - no - off {
+ $itk_component(entry) configure -state disabled
+ }
+ }
+ }
+ readonly {
+ $itk_component(entry) configure -state readonly
+ }
+ default {
+ error "bad state value \"$itk_option(-state)\":\
+ must be normal or disabled"
+ }
+ }
+ if {[info exists itk_component(arrowBtn)]} {
+ $itk_component(arrowBtn) configure -state $itk_option(-state)
+ }
+}
+
+# --------------------------------------------------------------------
+# OPTION: -unique
+#
+# Boolean which disallows/allows adding duplicate items to the listbox.
+# --------------------------------------------------------------------
+itcl::configbody iwidgets::Combobox::unique {
+ # boolean error check
+ switch -- $itk_option(-unique) {
+ 1 - true - yes - on { }
+ 0 - false - no - off { }
+ default {
+ error "bad unique value \"$itk_option(-unique)\":\
+ should be boolean"
+ }
+ }
+}
+
+# =================================================================
+# METHODS
+# =================================================================
+
+# ------------------------------------------------------
+# PUBLIC METHOD: clear ?component?
+#
+# Remove all elements from the listbox, all contents
+# from the entry component, or both (if all).
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::clear {{component all}} {
+ switch -- $component {
+ entry {
+ iwidgets::Entryfield::clear
+ }
+ list {
+ delete list 0 end
+ }
+ all {
+ delete list 0 end
+ iwidgets::Entryfield::clear
+ }
+ default {
+ error "bad Combobox component \"$component\":\
+ must be entry, list, or all."
+ }
+ }
+ return
+}
+
+# ------------------------------------------------------
+# PUBLIC METHOD: curselection
+#
+# Return the current selection index.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::curselection {} {
+ return [$itk_component(list) curselection]
+}
+
+# ------------------------------------------------------
+# PUBLIC METHOD: delete component first ?last?
+#
+# Delete an item or items from the listbox OR delete
+# text from the entry field. First argument determines
+# which component deletion occurs in - valid values are
+# entry or list.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::delete {component first {last {}}} {
+ switch -- $component {
+ entry {
+ if {$last == {}} {
+ set last [expr {$first + 1}]
+ }
+ iwidgets::Entryfield::delete $first $last
+ }
+ list {
+ _deleteList $first $last
+ }
+ default {
+ error "bad Combobox component \"$component\":\
+ must be entry or list."
+ }
+ }
+}
+
+# ------------------------------------------------------
+# PUBLIC METHOD: get ?index?
+#
+#
+# Retrieve entry contents if no args OR use args as list
+# index and retrieve list item at index .
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::get {{index {}}} {
+ # no args means to get the current text in the entry field area
+ if {$index == {}} {
+ iwidgets::Entryfield::get
+ } else {
+ eval $itk_component(list) get $index
+ }
+}
+
+# ------------------------------------------------------
+# PUBLIC METHOD: getcurselection
+#
+# Return currently selected item in the listbox. Shortcut
+# version of get curselection command combination.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::getcurselection {} {
+ return [$itk_component(list) getcurselection]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: invoke
+#
+# Pops up or down a dropdown combobox.
+#
+# ------------------------------------------------------------------
+itcl::body iwidgets::Combobox::invoke {} {
+ if {$itk_option(-dropdown)} {
+ return [_toggleList]
+ }
+ return
+}
+
+# ------------------------------------------------------------
+# PUBLIC METHOD: insert comonent index string ?string ...?
+#
+# Insert an item into the listbox OR text into the entry area.
+# Valid component names are entry or list.
+#
+# ------------------------------------------------------------
+itcl::body iwidgets::Combobox::insert {component index args} {
+ set nargs [llength $args]
+
+ if {$nargs == 0} {
+ error "no value given for parameter \"string\" in function\
+ \"Combobox::insert\""
+ }
+
+ switch -- $component {
+ entry {
+ if { $nargs > 1} {
+ error "called function \"Combobox::insert entry\"\
+ with too many arguments"
+ } else {
+ if {$itk_option(-state) == "normal"} {
+ eval iwidgets::Entryfield::insert $index $args
+ [itcl::code $this _lookup ""]
+ }
+ }
+ }
+ list {
+ if {$itk_option(-state) == "normal"} {
+ eval $itk_component(list) insert $index $args
+ }
+ }
+ default {
+ error "bad Combobox component \"$component\": must\
+ be entry or list."
+ }
+ }
+}
+
+# ------------------------------------------------------
+# PUBLIC METHOD: justify direction
+#
+# Wrapper for justifying the listbox items in one of
+# 4 directions: top, bottom, left, or right.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::justify {direction} {
+ return [$itk_component(list) justify $direction]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: see index
+#
+# Adjusts the view such that the element given by index is visible.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Combobox::see {index} {
+ return [$itk_component(list) see $index]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: selection option first ?last?
+#
+# Adjusts the selection within the listbox and changes the contents
+# of the entry component to be the value of the selected list item.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Combobox::selection {option first {last {}}} {
+ # thin wrap
+ if {$option == "set"} {
+ $itk_component(list) selection clear 0 end
+ $itk_component(list) selection set $first
+ set rtn ""
+ } else {
+ set rtn [eval $itk_component(list) selection $option $first $last]
+ }
+ set _currItem $first
+
+ # combobox additions
+ set theText [getcurselection]
+ if {$theText != [$itk_component(entry) get]} {
+ clear entry
+ if {$theText != ""} {
+ insert entry 0 $theText
+ }
+ }
+ return $rtn
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: size
+#
+# Returns a decimal string indicating the total number of elements
+# in the listbox.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Combobox::size {} {
+ return [$itk_component(list) size]
+}
+
+# ------------------------------------------------------
+# PUBLIC METHOD: sort ?mode?
+#
+# Sort the current list in either "ascending" or "descending" order.
+#
+# jss: how should i handle selected items?
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::sort {{mode ascending}} {
+ $itk_component(list) sort $mode
+ # return [$itk_component(list) sort $mode]
+}
+
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: xview ?arg arg ...?
+#
+# Change or query the vertical position of the text in the list box.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Combobox::xview {args} {
+ return [eval $itk_component(list) xview $args]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: yview ?arg arg ...?
+#
+# Change or query the horizontal position of the text in the list box.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Combobox::yview {args} {
+ return [eval $itk_component(list) yview $args]
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _addToList
+#
+# Add the current item in the entry to the listbox.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_addToList {} {
+ set input [get]
+ if {$input != ""} {
+ if {$itk_option(-unique)} {
+ # if item is already in list, select it and exit
+ set item [lsearch -exact [$itk_component(list) get 0 end] $input]
+ if {$item != -1} {
+ selection clear 0 end
+ if {$item != {}} {
+ selection set $item $item
+ set _currItem $item
+ }
+ return
+ }
+ }
+ # add the item to end of list
+ selection clear 0 end
+ insert list end $input
+ selection set end end
+ }
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _createComponents
+#
+# Create deferred combobox components and add bindings.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_createComponents {} {
+ if {$itk_option(-dropdown)} {
+ # --- build a dropdown combobox ---
+
+ # make the arrow childsite be on the right hand side
+
+ #-------------------------------------------------------------
+ # BUG FIX: csmith (Chad Smith: csmith@adc.com), 3/4/99
+ #-------------------------------------------------------------
+ # The following commented line of code overwrites the -command
+ # option when passed into the constructor. The order of calls
+ # in the constructor is:
+ # 1) eval itk_initalize $args (initializes -command)
+ # 2) _doLayout
+ # 3) _createComponents (overwrites -command)
+ # The solution is to only set the -command option if it hasn't
+ # already been set. The following 4 lines of code do this.
+ #-------------------------------------------------------------
+ # ** configure -childsitepos e -command [code $this _addToList]
+ #-------------------------------------------------------------
+ configure -childsitepos e
+ if ![llength [cget -command]] {
+ configure -command [itcl::code $this _addToList]
+ }
+
+ # arrow button to popup the list
+ itk_component add arrowBtn {
+ button $itk_interior.arrowBtn -borderwidth 2 \
+ -width 15 -height 15 -image downarrow \
+ -command [itcl::code $this _toggleList] -state $itk_option(-state)
+ } {
+ keep -background -borderwidth -cursor -state \
+ -highlightcolor -highlightthickness
+ rename -relief -arrowrelief arrowRelief Relief
+ rename -highlightbackground -background background Background
+ }
+
+ # popup list container
+ itk_component add popup {
+ toplevel $itk_interior.popup
+ } {
+ keep -background -cursor
+ }
+ wm withdraw $itk_interior.popup
+
+ # the listbox
+ itk_component add list {
+ iwidgets::Scrolledlistbox $itk_interior.popup.list -exportselection no \
+ -vscrollmode dynamic -hscrollmode dynamic -selectmode browse
+ } {
+ keep -background -borderwidth -cursor -foreground \
+ -highlightcolor -highlightthickness \
+ -hscrollmode -selectbackground \
+ -selectborderwidth -selectforeground -textbackground \
+ -textfont -vscrollmode
+ rename -height -listheight listHeight Height
+ rename -cursor -popupcursor popupCursor Cursor
+ }
+ # mode specific bindings
+ _dropdownBindings
+
+ # Ugly hack to avoid tk buglet revealed in _dropdownBtnRelease where
+ # relief is used but not set in scrollbar.tcl.
+ global tkPriv
+ set tkPriv(relief) raise
+
+ } else {
+ # --- build a simple combobox ---
+ configure -childsitepos s
+ itk_component add list {
+ iwidgets::Scrolledlistbox $itk_interior.list -exportselection no \
+ -vscrollmode dynamic -hscrollmode dynamic
+ } {
+ keep -background -borderwidth -cursor -foreground \
+ -highlightcolor -highlightthickness \
+ -hscrollmode -selectbackground \
+ -selectborderwidth -selectforeground -textbackground \
+ -textfont -visibleitems -vscrollmode
+ rename -height -listheight listHeight Height
+ }
+ # add mode specific bindings
+ _simpleBindings
+ }
+
+ # popup cursor applies only to the list within the combobox
+ configure -popupcursor $itk_option(-popupcursor)
+
+ # add mode independent bindings
+ _commonBindings
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _deleteList first ?last?
+#
+# Delete an item or items from the listbox. Called via
+# "delete list args".
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_deleteList {first {last {}}} {
+
+ if {$last == {}} {
+ set last $first
+ }
+ $itk_component(list) delete $first $last
+
+ # remove the item if it is no longer in the list
+ set text [$this get]
+ if {$text != ""} {
+ set index [lsearch -exact [$itk_component(list) get 0 end] $text ]
+ if {$index == -1} {
+ clear entry
+ }
+ }
+ return
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _deleteText first ?last?
+#
+# Renamed Entryfield delete method. Called via "delete entry args".
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_deleteText {first {last {}}} {
+ $itk_component(entry) configure -state normal
+ set rtrn [delete $first $last]
+ switch -- $itk_option(-editable) {
+ 0 - false - no - off {
+ $itk_component(entry) configure -state disabled
+ }
+ }
+ return $rtrn
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _doLayout ?when?
+#
+# Call methods to create and pack the Combobox components.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_doLayout {{when later}} {
+ _createComponents
+ _packComponents $when
+}
+
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _drawArrow
+#
+# Draw the arrow button. Determines packing according to
+# -labelpos.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_drawArrow {} {
+ set flip false
+ set relief ""
+ set fg [cget -foreground]
+ if {$_isPosted} {
+ set flip true
+ set relief "-relief sunken"
+ } else {
+ set relief "-relief $itk_option(-arrowrelief)"
+ }
+
+ if {$flip} {
+ #
+ # draw up arrow
+ #
+ eval $itk_component(arrowBtn) configure -image uparrow $relief
+ } else {
+ #
+ # draw down arrow
+ #
+ eval $itk_component(arrowBtn) configure -image downarrow $relief
+ }
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _dropdownBtnRelease window x y
+#
+# Event handler for button releases while a dropdown list
+# is posted.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_dropdownBtnRelease {{window {}} {x 1} {y 1}} {
+
+ # if it's a scrollbar then ignore the release
+ if {($window == [$itk_component(list) component vertsb]) ||
+ ($window == [$itk_component(list) component horizsb])} {
+ return
+ }
+
+ # 1st release allows list to stay up unless we are in listbox
+ if {$_ignoreRelease} {
+ _ignoreNextBtnRelease false
+ return
+ }
+
+ # should I use just the listbox or also include the scrollbars
+ if { ($x >= 0) && ($x < [winfo width [_slbListbox]])
+ && ($y >= 0) && ($y < [winfo height [_slbListbox]])} {
+ _stateSelect
+ }
+
+ _unpostList
+
+ # execute user command
+ if {$itk_option(-selectioncommand) != ""} {
+ uplevel #0 $itk_option(-selectioncommand)
+ }
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _ignoreNextBtnRelease ignore
+#
+# Set private variable _ignoreRelease. If this variable
+# is true then the next button release will not remove
+# a dropdown list.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_ignoreNextBtnRelease {ignore} {
+ set _ignoreRelease $ignore
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _next
+#
+# Select the next item in the list.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_next {} {
+
+ set _next_prevFLAG 1
+
+ if {[size] <= 1} {
+ return
+ }
+ set i [curselection]
+ if {($i == {}) || ($i == ([size]-1)) } {
+ set i 0
+ } else {
+ incr i
+ }
+ selection clear 0 end
+ selection set $i $i
+ see $i
+ set _currItem $i
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _packComponents ?when?
+#
+# Pack the components of the combobox and add bindings.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_packComponents {{when later}} {
+ if {$when == "later"} {
+ if {$_repacking == ""} {
+ set _repacking [after idle [itcl::code $this _packComponents now]]
+ return
+ }
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ if {$itk_option(-dropdown)} {
+ grid configure $itk_component(list) -row 1 -column 0 -sticky news
+ _resizeArrow
+ grid config $itk_component(arrowBtn) -row 0 -column 1 -sticky nsew
+ } else {
+ # size and pack list hack
+ grid configure $itk_component(entry) -row 0 -column 0 -sticky ew
+ grid configure $itk_component(efchildsite) -row 1 -column 0 -sticky nsew
+ grid configure $itk_component(list) -row 0 -column 0 -sticky nsew
+
+ grid rowconfigure $itk_component(efchildsite) 1 -weight 1
+ grid columnconfigure $itk_component(efchildsite) 0 -weight 1
+ }
+ set _repacking ""
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _positionList
+#
+# Determine the position (geometry) for the popped up list
+# and map it to the screen.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_positionList {} {
+
+ set x [winfo rootx $itk_component(entry) ]
+ set y [expr {[winfo rooty $itk_component(entry) ] + \
+ [winfo height $itk_component(entry) ]}]
+ set w [winfo width $itk_component(entry) ]
+ set h [winfo height [_slbListbox] ]
+ set sh [winfo screenheight .]
+
+ if {(($y+$h) > $sh) && ($y > ($sh/2))} {
+ set y [expr {[winfo rooty $itk_component(entry) ] - $h}]
+ }
+
+ $itk_component(list) configure -width $w
+ wm overrideredirect $itk_component(popup) 0
+ wm geometry $itk_component(popup) +$x+$y
+ wm overrideredirect $itk_component(popup) 1
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _postList
+#
+# Pop up the list in a dropdown style Combobox.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_postList {} {
+ if {[$itk_component(list) size] == ""} {
+ return
+ }
+
+ set _isPosted true
+ _positionList
+
+ # map window and do a grab
+ wm deiconify $itk_component(popup)
+ _listShowing -wait
+
+ # Added by csmith, 12/19/00. Thanks to Erik Leunissen for
+ # finding this problem. We need to restore any previous
+ # grabs after the dropdown listbox is withdrawn. To do this,
+ # save the currently grabbed window. It is then restored in
+ # the _unpostList method.
+ set _grab(window) [::grab current]
+ if {$_grab(window) != ""} {
+ set _grab(status) [::grab status $_grab(window)]
+ }
+
+ # Now grab the dropdown listbox.
+ if {$itk_option(-grab) == "global"} {
+ ::grab -global $itk_component(popup)
+ } else {
+ ::grab $itk_component(popup)
+ }
+ raise $itk_component(popup)
+ focus $itk_component(popup)
+ _drawArrow
+
+ # Added by csmith, 10/26/00. This binding keeps the listbox
+ # from staying mapped if the window in which the combobox
+ # is packed is iconified.
+ bind $itk_component(entry) <Unmap> [itcl::code $this _unpostList]
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _previous
+#
+# Select the previous item in the list. Wraps at front
+# and end of list.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_previous {} {
+
+ set _next_prevFLAG 1
+
+ if {[size] <= 1} {
+ return
+ }
+ set i [curselection]
+ if {$i == "" || $i == 0} {
+ set i [expr {[size] - 1}]
+ } else {
+ incr i -1
+ }
+ selection clear 0 end
+ selection set $i $i
+ see $i
+ set _currItem $i
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _resizeArrow
+#
+# Recalculate the arrow button size and then redraw it.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_resizeArrow {} {
+ set bw [expr {[$itk_component(arrowBtn) cget -borderwidth]+ \
+ [$itk_component(arrowBtn) cget -highlightthickness]}]
+ set newHeight [expr {[winfo reqheight $itk_component(entry)]-(2*$bw) - 2}]
+ $itk_component(arrowBtn) configure -width $newHeight -height $newHeight
+ _drawArrow
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _selectCmd
+#
+# Called when list item is selected to insert new text
+# in entry, and call user -command callback if defined.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_selectCmd {} {
+ $itk_component(entry) configure -state normal
+
+ set _currItem [$itk_component(list) curselection]
+ set item [$itk_component(list) getcurselection]
+ clear entry
+ $itk_component(entry) insert 0 $item
+ switch -- $itk_option(-editable) {
+ 0 - false - no - off {
+ $itk_component(entry) configure -state disabled
+ }
+ }
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _toggleList
+#
+# Post or unpost the dropdown listbox (toggle).
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_toggleList {} {
+ if {[winfo ismapped $itk_component(popup)] } {
+ _unpostList
+ } else {
+ _postList
+ }
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _unpostList
+#
+# Unmap the listbox (pop it down).
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_unpostList {} {
+ # Determine if event occured in the scrolledlistbox and, if it did,
+ # don't unpost it. (A selection in the list unposts it correctly and
+ # in the scrollbar we don't want to unpost it.)
+ set x [winfo x $itk_component(list)]
+ set y [winfo y $itk_component(list)]
+ set w [winfo width $itk_component(list)]
+ set h [winfo height $itk_component(list)]
+
+ wm withdraw $itk_component(popup)
+ ::grab release $itk_component(popup)
+
+ # Added by csmith, 12/19/00. Thanks to Erik Leunissen for finding
+ # this problem. We need to restore any previous grabs when the
+ # dropdown listbox is unmapped.
+ if {$_grab(window) != ""} {
+ if {$_grab(status) == "global"} {
+ ::grab -global $_grab(window)
+ } else {
+ ::grab $_grab(window)
+ }
+ set _grab(window) ""
+ set _grab(status) ""
+ }
+
+ # Added by csmith, 10/26/00. This binding resets the binding
+ # created in _postList - see that method for further details.
+ bind $itk_component(entry) <Unmap> {}
+
+ set _isPosted false
+
+ $itk_component(list) selection clear 0 end
+ if {$_currItem != {}} {
+ $itk_component(list) selection set $_currItem $_currItem
+ $itk_component(list) activate $_currItem
+ }
+
+ switch -- $itk_option(-editable) {
+ 1 - true - yes - on {
+ $itk_component(entry) configure -state normal
+ }
+ 0 - false - no - off {
+ $itk_component(entry) configure -state disabled
+ }
+ }
+
+ _drawArrow
+ update
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _commonBindings
+#
+# Bindings that are used by both simple and dropdown
+# style Comboboxes.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_commonBindings {} {
+ bind $itk_component(entry) <KeyPress-BackSpace> [itcl::code $this _bs]
+ bind $itk_component(entry) <KeyRelease> [itcl::code $this _lookup %K]
+ bind $itk_component(entry) <Down> [itcl::code $this _next]
+ bind $itk_component(entry) <Up> [itcl::code $this _previous]
+ bind $itk_component(entry) <Control-n> [itcl::code $this _next]
+ bind $itk_component(entry) <Control-p> [itcl::code $this _previous]
+ bind [_slbListbox] <Control-n> [itcl::code $this _next]
+ bind [_slbListbox] <Control-p> [itcl::code $this _previous]
+}
+
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _dropdownBindings
+#
+# Bindings used only by the dropdown type Combobox.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_dropdownBindings {} {
+ bind $itk_component(popup) <Escape> [itcl::code $this _unpostList]
+ bind $itk_component(popup) <space> \
+ "[itcl::code $this _stateSelect]; [itcl::code $this _unpostList]"
+ bind $itk_component(popup) <Return> \
+ "[itcl::code $this _stateSelect]; [itcl::code $this _unpostList]"
+ bind $itk_component(popup) <ButtonRelease-1> \
+ [itcl::code $this _dropdownBtnRelease %W %x %y]
+
+ bind $itk_component(list) <Map> \
+ [itcl::code $this _listShowing 1]
+ bind $itk_component(list) <Unmap> \
+ [itcl::code $this _listShowing 0]
+
+ # once in the listbox, we drop on the next release (unless in scrollbar)
+ bind [_slbListbox] <Enter> \
+ [itcl::code $this _ignoreNextBtnRelease false]
+
+ bind $itk_component(arrowBtn) <3> [itcl::code $this _next]
+ bind $itk_component(arrowBtn) <Shift-3> [itcl::code $this _previous]
+ bind $itk_component(arrowBtn) <Down> [itcl::code $this _next]
+ bind $itk_component(arrowBtn) <Up> [itcl::code $this _previous]
+ bind $itk_component(arrowBtn) <Control-n> [itcl::code $this _next]
+ bind $itk_component(arrowBtn) <Control-p> [itcl::code $this _previous]
+ bind $itk_component(arrowBtn) <Shift-Down> [itcl::code $this _toggleList]
+ bind $itk_component(arrowBtn) <Shift-Up> [itcl::code $this _toggleList]
+ bind $itk_component(arrowBtn) <Return> [itcl::code $this _toggleList]
+ bind $itk_component(arrowBtn) <space> [itcl::code $this _toggleList]
+
+ bind $itk_component(entry) <Configure> [itcl::code $this _resizeArrow]
+ bind $itk_component(entry) <Shift-Down> [itcl::code $this _toggleList]
+ bind $itk_component(entry) <Shift-Up> [itcl::code $this _toggleList]
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _simpleBindings
+#
+# Bindings used only by the simple type Comboboxes.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_simpleBindings {} {
+ bind [_slbListbox] <ButtonRelease-1> [itcl::code $this _stateSelect]
+ bind [_slbListbox] <space> [itcl::code $this _stateSelect]
+ bind [_slbListbox] <Return> [itcl::code $this _stateSelect]
+ bind $itk_component(entry) <Escape> ""
+ bind $itk_component(entry) <Shift-Down> ""
+ bind $itk_component(entry) <Shift-Up> ""
+ bind $itk_component(entry) <Configure> ""
+}
+
+# ------------------------------------------------------
+# PROTECTED METHOD: _listShowing ?val?
+#
+# Used instead of "tkwait visibility" to make sure that
+# the dropdown list is visible. Whenever the list gets
+# mapped or unmapped, this method is called to keep
+# track of it. When it is called with the value "-wait",
+# it waits for the list to be mapped.
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_listShowing {{val ""}} {
+ if {$val == ""} {
+ return $_listShowing($this)
+ } elseif {$val == "-wait"} {
+ while {!$_listShowing($this)} {
+ tkwait variable [itcl::scope _listShowing($this)]
+ }
+ return
+ }
+ set _listShowing($this) $val
+}
+
+# ------------------------------------------------------
+# PRIVATE METHOD: _slbListbox
+#
+# Access the tk listbox window out of the scrolledlistbox.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_slbListbox {} {
+ return [$itk_component(list) component listbox]
+}
+
+# ------------------------------------------------------
+# PRIVATE METHOD: _stateSelect
+#
+# only allows a B1 release in the listbox to have an effect if -state is
+# normal.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_stateSelect {} {
+ switch -- $itk_option(-state) {
+ normal {
+ [itcl::code $this _selectCmd]
+ }
+ }
+}
+
+# ------------------------------------------------------
+# PRIVATE METHOD: _bs
+#
+# A part of the auto-completion code, this function sets a flag when the
+# Backspace key is hit and there is a selection in the entry field.
+# Note that it's probably buggy to assume that a selection being present
+# means that that selection came from auto-completion.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_bs {} {
+ #
+ # exit if completion is turned off
+ #
+ switch -- $itk_option(-completion) {
+ 0 - no - false - off {
+ return
+ }
+ }
+ #
+ # critical section flag. it ain't perfect, but for most usage it'll
+ # keep us from being in this code "twice" at the same time
+ # (auto-repeated keystrokes are a pain!)
+ #
+ if {$_inbs} {
+ return
+ } else {
+ set _inbs 1
+ }
+
+ #
+ # set the _doit flag if there is a selection set in the entry field
+ #
+ set _doit 0
+ if [$itk_component(entry) selection present] {
+ set _doit 1
+ }
+
+ #
+ # clear the semaphore and return
+ #
+ set _inbs 0
+}
+
+# ------------------------------------------------------
+# PRIVATE METHOD: _lookup
+#
+# handles auto-completion of text typed (or insert'd) into the entry field.
+#
+# ------------------------------------------------------
+itcl::body iwidgets::Combobox::_lookup {key} {
+
+ #
+ # Don't process auto-completion stuff if navigation key was released
+ # Fixes SF bug 501300
+ #
+ if {$_next_prevFLAG} {
+ set _next_prevFLAG 0
+ return
+ }
+
+ #
+ # exit if completion is turned off
+ #
+ switch -- $itk_option(-completion) {
+ 0 - no - false - off {
+ return
+ }
+ }
+
+ #
+ # critical section flag. it ain't perfect, but for most usage it'll
+ # keep us from being in this code "twice" at the same time
+ # (auto-repeated keystrokes are a pain!)
+ #
+ if {$_inlookup} {
+ return
+ } else {
+ set _inlookup 1
+ }
+
+ #
+ # if state of megawidget is disabled, or the entry is not editable,
+ # clear the semaphore and exit
+ #
+ if {$itk_option(-state) == "disabled" \
+ || [lsearch {on 1 true yes} $itk_option(-editable)] == -1} {
+ set _inlookup 0
+ return
+ }
+
+ #
+ # okay, *now* we can get to work
+ # the _bs function is called on keyPRESS of BackSpace, and will set
+ # the _doit flag if there's a selection set in the entryfield. If
+ # there is, we're assuming that it's generated by completion itself
+ # (this is probably a Bad Assumption), so we'll want to whack the
+ # selected text, as well as the character immediately preceding the
+ # insertion cursor.
+ #
+ if {$key == "BackSpace"} {
+ if {$_doit} {
+ set first [expr {[$itk_component(entry) index insert] -1}]
+ $itk_component(entry) delete $first end
+ $itk_component(entry) icursor $first
+ }
+ }
+
+ #
+ # get the text left in the entry field, and its length. if
+ # zero-length, clear the selection in the listbox, clear the
+ # semaphore, and boogie.
+ #
+ set text [get]
+ set len [string length $text]
+ if {$len == 0} {
+ $itk_component(list) selection clear 0 end
+ set _inlookup 0
+ return
+ }
+
+ # No need to do lookups for Shift keys or Arrows. The up/down
+ # arrow keys should walk up/down the listbox entries.
+ switch $key {
+ Shift_L - Shift_R - Up - Down - Left - Right {
+ set _inlookup 0
+ return
+ }
+ default { }
+ }
+
+ # Added by csmith 12/11/01 to resolve SF ticket #474817. It's an unusual
+ # circumstance, but we need to make sure the character passed into this
+ # method matches the last character in the entry's text string. It's
+ # possible to type fast enough that the _lookup method gets invoked
+ # *after* multiple characters have been typed and *before* the first
+ # character has been processed. For example, you can type "bl" very
+ # quickly, and by the time the interpreter processes "b", the "l" has
+ # already been placed in the entry field. This causes problems as noted
+ # in the SF ticket.
+ #
+ # Thus, if the character currently being processed does not match the
+ # last character in the entry field, reset the _inlookup flag and return.
+ # Also, note that we're only concerned with single characters here, not
+ # keys such as backspace, delete, etc.
+ if {$key != [string range $text end end] && [string match ? $key]} {
+ set _inlookup 0
+ return
+ }
+
+ #
+ # okay, so we have to do a lookup. find the first match in the
+ # listbox to the text we've got in the entry field (glob).
+ # if one exists, clear the current listbox selection, and set it to
+ # the one we just found, making that one visible in the listbox.
+ # then, pick off the text from the listbox entry that hadn't yet been
+ # entered into the entry field. we need to tack that text onto the
+ # end of the entry field, select it, and then set the insertion cursor
+ # back to just before the point where we just added that text.
+ # if one didn't exist, then just clear the listbox selection
+ #
+ set item [lsearch [$itk_component(list) get 0 end] "$text*" ]
+ if {$item != -1} {
+ $itk_component(list) selection clear 0 end
+ $itk_component(list) selection set $item $item
+ see $item
+ set remainder [string range [$itk_component(list) get $item] $len end]
+ $itk_component(entry) insert end $remainder
+ $itk_component(entry) selection range $len end
+ $itk_component(entry) icursor $len
+ } else {
+ $itk_component(list) selection clear 0 end
+ }
+ #
+ # clear the semaphore and return
+ #
+ set _inlookup 0
+ return
+}
diff --git a/iwidgets/generic/dateentry.itk b/iwidgets/generic/dateentry.itk
new file mode 100644
index 00000000000..0e8c146e7bf
--- /dev/null
+++ b/iwidgets/generic/dateentry.itk
@@ -0,0 +1,424 @@
+#
+# Dateentry
+# ----------------------------------------------------------------------
+# Implements a quicken style date entry field with a popup calendar
+# by combining the datefield and calendar widgets together. This
+# allows a user to enter the date via the keyboard or by using the
+# mouse by selecting the calendar icon which brings up a popup calendar.
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts E-mail: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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.
+# ======================================================================
+#
+# ----------------------------------------------------------------------
+#
+# Modified 2001-10-23 by Mark Alston to pass options to the datefield
+# constructor. Needed to allow use of new option -int which lets the
+# user use dates in YYYY-MM-DD format as well as MM/DD/YYYY format.
+#
+# option -int yes sets dates to YYYY-MM-DD format
+# -int no sets dates to MM/DD/YYYY format.
+#
+# ----------------------------------------------------------------------
+#
+# Usual options.
+#
+itk::usual Dateentry {
+ keep -background -borderwidth -currentdatefont -cursor \
+ -datefont -dayfont -foreground -highlightcolor \
+ -highlightthickness -labelfont -textbackground -textfont \
+ -titlefont -int
+}
+
+# ------------------------------------------------------------------
+# DATEENTRY
+# ------------------------------------------------------------------
+itcl::class iwidgets::Dateentry {
+ inherit iwidgets::Datefield
+
+ constructor {args} {
+ eval Datefield::constructor $args
+ } {}
+
+ itk_option define -grab grab Grab "global"
+ itk_option define -icon icon Icon {}
+
+ #
+ # The calendar widget isn't created until needed, yet we need
+ # its options to be available upon creation of a dateentry widget.
+ # So, we'll define them in these class now so they can just be
+ # propagated onto the calendar later.
+ #
+ itk_option define -days days Days {Su Mo Tu We Th Fr Sa}
+ itk_option define -forwardimage forwardImage Image {}
+ itk_option define -backwardimage backwardImage Image {}
+ itk_option define -weekdaybackground weekdayBackground Background \#d9d9d9
+ itk_option define -weekendbackground weekendBackground Background \#d9d9d9
+ itk_option define -outline outline Outline \#d9d9d9
+ itk_option define -buttonforeground buttonForeground Foreground blue
+ itk_option define -foreground foreground Foreground black
+ itk_option define -selectcolor selectColor Foreground red
+ itk_option define -selectthickness selectThickness SelectThickness 3
+ itk_option define -titlefont titleFont Font \
+ -*-helvetica-bold-r-normal--*-140-*
+ itk_option define -dayfont dayFont Font \
+ -*-helvetica-medium-r-normal--*-120-*
+ itk_option define -datefont dateFont Font \
+ -*-helvetica-medium-r-normal--*-120-*
+ itk_option define -currentdatefont currentDateFont Font \
+ -*-helvetica-bold-r-normal--*-120-*
+ itk_option define -startday startDay Day sunday
+ itk_option define -height height Height 165
+ itk_option define -width width Width 200
+ itk_option define -state state State normal
+
+ protected {
+ method _getPopupDate {date}
+ method _releaseGrab {}
+ method _releaseGrabCheck {rootx rooty}
+ method _popup {}
+ method _getDefaultIcon {}
+
+ common _defaultIcon ""
+ }
+}
+
+#
+# Provide a lowercased access method for the dateentry class.
+#
+proc ::iwidgets::dateentry {pathName args} {
+ uplevel ::iwidgets::Dateentry $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dateentry::constructor {args} {
+ #
+ # Create an icon label to act as a button to bring up the
+ # calendar popup.
+ #
+ itk_component add iconbutton {
+ label $itk_interior.iconbutton -relief raised
+ } {
+ keep -borderwidth -cursor -foreground
+ }
+ grid $itk_component(iconbutton) -row 0 -column 0 -sticky ns
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -icon
+#
+# Specifies the calendar icon image to be used in the date.
+# Should one not be provided, then a default pixmap will be used
+# if possible, bitmap otherwise.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Dateentry::icon {
+ if {$itk_option(-icon) == {}} {
+ $itk_component(iconbutton) configure -image [_getDefaultIcon]
+ } else {
+ if {[lsearch [image names] $itk_option(-icon)] == -1} {
+ error "bad icon option \"$itk_option(-icon)\":\
+ should be an existing image"
+ } else {
+ $itk_component(iconbutton) configure -image $itk_option(-icon)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -grab
+#
+# Specifies the grab level, local or global, to be obtained when
+# bringing up the popup calendar. The default is global.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Dateentry::grab {
+ switch -- $itk_option(-grab) {
+ "local" - "global" {}
+ default {
+ error "bad grab option \"$itk_option(-grab)\":\
+ should be local or global"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -state
+#
+# Specifies the state of the widget which may be disabled or
+# normal. A disabled state prevents selection of the date field
+# or date icon button.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Dateentry::state {
+ switch -- $itk_option(-state) {
+ normal {
+ bind $itk_component(iconbutton) <Button-1> [itcl::code $this _popup]
+ }
+ disabled {
+ bind $itk_component(iconbutton) <Button-1> {}
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _getDefaultIcon
+#
+# This method is invoked uto retrieve the name of the default icon
+# image displayed in the icon button.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dateentry::_getDefaultIcon {} {
+ if {[lsearch [image types] pixmap] != -1} {
+ set _defaultIcon [image create pixmap -data {
+ /* XPM */
+ static char *calendar[] = {
+ /* width height num_colors chars_per_pixel */
+ " 25 20 6 1",
+ /* colors */
+ ". c #808080",
+ "# c #040404",
+ "a c #848484",
+ "b c #fc0404",
+ "c c #fcfcfc",
+ "d c #c0c0c0",
+ /* pixels */
+ "d##########d###########dd",
+ "d#ccccccccc##ccccccccca#d",
+ "##ccccccccc.#ccccccccc..#",
+ "##cccbbcccca#cccbbbccca.#",
+ "##cccbbcccc.#ccbbbbbcc..#",
+ "##cccbbccc####ccccbbcc..#",
+ "##cccbbcccca#ccccbbbcca.#",
+ "##cccbbcccc.#cccbbbccc..#",
+ "##cccbbcccca#ccbbbcccca.#",
+ "##cccbbbccc.#ccbbbbbcc..#",
+ "##ccccccccc.#ccccccccc..#",
+ "##ccccccccca#ccccccccca.#",
+ "##cc#####c#cd#c#####cc..#",
+ "##cccccccc####cccccccca.#",
+ "##cc#####cc.#cc#####cc..#",
+ "##ccccccccc.#ccccccccc..#",
+ "##ccccccccc.#ccccccccc..#",
+ "##..........#...........#",
+ "###..........#..........#",
+ "#########################"
+ };
+ }]
+ } else {
+ set _defaultIcon [image create bitmap -data {
+ #define calendr2_width 25
+ #define calendr2_height 20
+ static char calendr2_bits[] = {
+ 0xfe,0xf7,0x7f,0xfe,0x02,0x18,0xc0,0xfe,0x03,
+ 0x18,0x80,0xff,0x63,0x10,0x47,0xff,0x43,0x98,
+ 0x8a,0xff,0x63,0x3c,0x4c,0xff,0x43,0x10,0x8a,
+ 0xff,0x63,0x18,0x47,0xff,0x23,0x90,0x81,0xff,
+ 0xe3,0x98,0x4e,0xff,0x03,0x10,0x80,0xff,0x03,
+ 0x10,0x40,0xff,0xf3,0xa5,0x8f,0xff,0x03,0x3c,
+ 0x40,0xff,0xf3,0x99,0x8f,0xff,0x03,0x10,0x40,
+ 0xff,0x03,0x18,0x80,0xff,0x57,0x55,0x55,0xff,
+ 0x57,0xb5,0xaa,0xff,0xff,0xff,0xff,0xff};
+ }]
+ }
+
+ #
+ # Since this image will only need to be created once, we redefine
+ # this method to just return the image name for subsequent calls.
+ #
+ itcl::body ::iwidgets::Dateentry::_getDefaultIcon {} {
+ return $_defaultIcon
+ }
+
+ return $_defaultIcon
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _popup
+#
+# This method is invoked upon selection of the icon button. It
+# creates a calendar widget within a toplevel popup, calculates
+# the position at which to display the calendar, performs a grab
+# and displays the calendar.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dateentry::_popup {} {
+ #
+ # First, let's nullify the icon binding so that any another
+ # selections are ignored until were done with this one. Next,
+ # change the relief of the icon.
+ #
+ bind $itk_component(iconbutton) <Button-1> {}
+ $itk_component(iconbutton) configure -relief sunken
+
+ #
+ # Create a withdrawn toplevel widget and remove the window
+ # decoration via override redirect.
+ #
+ itk_component add -private popup {
+ toplevel $itk_interior.popup
+ }
+ $itk_component(popup) configure -borderwidth 2 -background black
+ wm withdraw $itk_component(popup)
+ wm overrideredirect $itk_component(popup) 1
+
+ #
+ # Add a binding to button 1 events in order to detect mouse
+ # clicks off the calendar in which case we'll release the grab.
+ # Also add a binding for Escape to always release.
+ #
+ bind $itk_component(popup) <1> [itcl::code $this _releaseGrabCheck %X %Y]
+ bind $itk_component(popup) <KeyPress-Escape> [itcl::code $this _releaseGrab]
+
+ #
+ # Create the calendar widget and set its cursor properly.
+ #
+ itk_component add calendar {
+ iwidgets::Calendar $itk_component(popup).calendar \
+ -command [itcl::code $this _getPopupDate %d] \
+ -int $itk_option(-int)
+ } {
+ usual
+ keep -days -forwardimage -backwardimage -weekdaybackground \
+ -weekendbackground -outline -buttonforeground -selectcolor \
+ -selectthickness -titlefont -dayfont -datefont \
+ -currentdatefont -startday -width -height
+ }
+ grid $itk_component(calendar) -row 0 -column 0
+ $itk_component(calendar) configure -cursor top_left_arrow
+
+ #
+ # The icon button will be used as the basis for the position of the
+ # popup on the screen. We'll always attempt to locate the popup
+ # off the lower right corner of the button. If that would put
+ # the popup off the screen, then we'll put above the upper left.
+ #
+ set rootx [winfo rootx $itk_component(iconbutton)]
+ set rooty [winfo rooty $itk_component(iconbutton)]
+ set popupwidth [winfo reqwidth $itk_component(popup)]
+ set popupheight [winfo reqheight $itk_component(popup)]
+
+ set popupx [expr {$rootx + 3 + \
+ [winfo width $itk_component(iconbutton)]}]
+ set popupy [expr {$rooty + 3 + \
+ [winfo height $itk_component(iconbutton)]}]
+
+ if {(($popupx + $popupwidth) > [winfo screenwidth .]) || \
+ (($popupy + $popupheight) > [winfo screenheight .])} {
+ set popupx [expr {$rootx - 3 - $popupwidth}]
+ set popupy [expr {$rooty - 3 - $popupheight}]
+ }
+
+ #
+ # Get the current date from the datefield widget and both
+ # show and select it on the calendar.
+ #
+ # Added catch for bad dates. Calendar then shows current date.
+ if [catch "$itk_component(calendar) show [get]" err] {
+ $itk_component(calendar) show now
+ $itk_component(calendar) select now
+ } else {
+ $itk_component(calendar) select [get]
+ }
+ #
+ # Display the popup at the calculated position.
+ #
+ wm geometry $itk_component(popup) +$popupx+$popupy
+ wm deiconify $itk_component(popup)
+ tkwait visibility $itk_component(popup)
+
+ #
+ # Perform either a local or global grab based on the -grab option.
+ #
+ if {$itk_option(-grab) == "local"} {
+ grab $itk_component(popup)
+ } else {
+ grab -global $itk_component(popup)
+ }
+
+ #
+ # Make sure the widget is above all others and give it focus.
+ #
+ raise $itk_component(popup)
+ focus $itk_component(calendar)
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _popupGetDate
+#
+# This method is the callback for selection of a date on the
+# calendar. It releases the grab and sets the date in the
+# datefield widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dateentry::_getPopupDate {date} {
+ _releaseGrab
+ show $date
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _releaseGrabCheck rootx rooty
+#
+# This method handles mouse button 1 events. If the selection
+# occured within the bounds of the calendar, then return normally
+# and let the calendar handle the event. Otherwise, we'll drop
+# the calendar and release the grab.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dateentry::_releaseGrabCheck {rootx rooty} {
+ set calx [winfo rootx $itk_component(calendar)]
+ set caly [winfo rooty $itk_component(calendar)]
+ set calwidth [winfo reqwidth $itk_component(calendar)]
+ set calheight [winfo reqheight $itk_component(calendar)]
+
+ if {($rootx < $calx) || ($rootx > ($calx + $calwidth)) || \
+ ($rooty < $caly) || ($rooty > ($caly + $calheight))} {
+ _releaseGrab
+ return -code break
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _releaseGrab
+#
+# This method releases the grab, destroys the popup, changes the
+# relief of the button back to raised and reapplies the binding
+# to the icon button that engages the popup action.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dateentry::_releaseGrab {} {
+ grab release $itk_component(popup)
+ $itk_component(iconbutton) configure -relief raised
+ destroy $itk_component(popup)
+ bind $itk_component(iconbutton) <Button-1> [itcl::code $this _popup]
+}
diff --git a/iwidgets/generic/datefield.itk b/iwidgets/generic/datefield.itk
new file mode 100644
index 00000000000..22c885d00fc
--- /dev/null
+++ b/iwidgets/generic/datefield.itk
@@ -0,0 +1,1021 @@
+#
+# Datefield
+# ----------------------------------------------------------------------
+# Implements a date entry field with adjustable built-in intelligence
+# levels.
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts E-mail: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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 Datefield {
+ keep -background -borderwidth -cursor -foreground -highlightcolor \
+ -highlightthickness -labelfont -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# DATEFIELD
+# ------------------------------------------------------------------
+itcl::class iwidgets::Datefield {
+ inherit iwidgets::Labeledwidget
+
+ constructor {args} {}
+
+ itk_option define -childsitepos childSitePos Position e
+ itk_option define -command command Command {}
+ itk_option define -iq iq Iq high
+ itk_option define -gmt gmt GMT no
+ itk_option define -int int DateFormat no
+
+ public method get {{format "-string"}}
+ public method isvalid {}
+ public method show {{date now}}
+
+ protected method _backward {}
+ protected method _focusIn {}
+ protected method _forward {}
+ protected method _keyPress {char sym state}
+ protected method _lastDay {month year}
+ protected method _moveField {direction}
+ protected method _setField {field}
+ protected method _whichField {}
+
+ protected variable _cfield "month"
+ protected variable _fields {month day year}
+}
+
+
+#
+# Provide a lowercased access method for the datefield class.
+#
+proc ::iwidgets::datefield {pathName args} {
+ uplevel ::iwidgets::Datefield $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Datefield.justify center widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::constructor {args} {
+ component hull configure -borderwidth 0
+
+ #
+ # Create an entry field for entering the date.
+ #
+ itk_component add date {
+ entry $itk_interior.date -width 10
+ } {
+ keep -borderwidth -cursor -exportselection \
+ -foreground -highlightcolor -highlightthickness \
+ -insertbackground -justify -relief -state
+
+ rename -font -textfont textFont Font
+ rename -highlightbackground -background background Background
+ rename -background -textbackground textBackground Background
+ }
+
+ #
+ # Create the child site widget.
+ #
+ itk_component add -protected dfchildsite {
+ frame $itk_interior.dfchildsite
+ }
+ set itk_interior $itk_component(dfchildsite)
+
+ #
+ # Add datefield event bindings for focus in and keypress events.
+ #
+ bind $itk_component(date) <FocusIn> [itcl::code $this _focusIn]
+ bind $itk_component(date) <KeyPress> [itcl::code $this _keyPress %A %K %s]
+
+ #
+ # Disable some mouse button event bindings:
+ # Button Motion
+ # Double-Clicks
+ # Triple-Clicks
+ # Button2
+ #
+ bind $itk_component(date) <Button1-Motion> break
+ bind $itk_component(date) <Button2-Motion> break
+ bind $itk_component(date) <Double-Button> break
+ bind $itk_component(date) <Triple-Button> break
+ bind $itk_component(date) <2> break
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+
+ #
+ # Initialize the date to the current date.
+ #
+ $itk_component(date) delete 0 end
+
+ show now
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -childsitepos
+#
+# Specifies the position of the child site in the widget. Valid
+# locations are n, s, e, and w.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Datefield::childsitepos {
+ set parent [winfo parent $itk_component(date)]
+
+ switch $itk_option(-childsitepos) {
+ n {
+ grid $itk_component(dfchildsite) -row 0 -column 0 -sticky ew
+ grid $itk_component(date) -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(dfchildsite) -row 0 -column 1 -sticky ns
+ grid $itk_component(date) -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(dfchildsite) -row 1 -column 0 -sticky ew
+ grid $itk_component(date) -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(dfchildsite) -row 0 -column 0 -sticky ns
+ grid $itk_component(date) -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: -command
+#
+# Command invoked upon detection of return key press event.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Datefield::command {}
+
+# ------------------------------------------------------------------
+# OPTION: -iq
+#
+# Specifies the level of intelligence to be shown in the actions
+# taken by the date field during the processing of keypress events.
+# Valid settings include high, average, and low. With a high iq,
+# the date prevents the user from typing in an invalid date. For
+# example, if the current date is 05/31/1997 and the user changes
+# the month to 04, then the day will be instantly modified for them
+# to be 30. In addition, leap years are fully taken into account.
+# With average iq, the month is limited to the values of 01-12, but
+# it is possible to type in an invalid day. A setting of low iq
+# instructs the widget to do no validity checking at all during
+# date entry. With both average and low iq levels, it is assumed
+# that the validity will be determined at a later time using the
+# date's isvalid command.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Datefield::iq {
+ switch $itk_option(-iq) {
+ high - average - low {
+ }
+ default {
+ error "bad iq option \"$itk_option(-iq)\":\
+ should be high, average or low"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -int
+#
+# Added by Mark Alston 2001/10/21
+#
+# Allows for the use of dates in "international" format: YYYY-MM-DD.
+# It must be a boolean value.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Datefield::int {
+ switch $itk_option(-int) {
+ 1 - yes - true - on {
+ set _cfield "year"
+ set _fields {year month day}
+ }
+ 0 - no - false - off { }
+ default {
+ error "bad int option \"$itk_option(-int)\": should be boolean"
+ }
+ }
+ show [get]
+}
+
+# ------------------------------------------------------------------
+# OPTION: -gmt
+#
+# This option is used for GMT time. Must be a boolean value.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Datefield::gmt {
+ switch $itk_option(-gmt) {
+ 0 - no - false - off { }
+ 1 - yes - true - on { }
+ default {
+ error "bad gmt option \"$itk_option(-gmt)\": should be boolean"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: get ?format?
+#
+# Return the current contents of the datefield in one of two formats
+# string or as an integer clock value using the -string and -clicks
+# options respectively. The default is by string. Reference the
+# clock command for more information on obtaining dates and their
+# formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::get {{format "-string"}} {
+ set datestr [$itk_component(date) get]
+
+ switch -- $format {
+ "-string" {
+ return $datestr
+ }
+ "-clicks" {
+ return [clock scan $datestr]
+ }
+ default {
+ error "bad format option \"$format\":\
+ should be -string or -clicks"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: show date
+#
+# Changes the currently displayed date to be that of the date
+# argument. The date may be specified either as a string or an
+# integer clock value. Reference the clock command for more
+# information on obtaining dates and their formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::show {{date "now"}} {
+ $itk_component(date) delete 0 end
+ if {$itk_option(-int)} {
+ set format {%Y-%m-%d}
+ } else {
+ set format {%m/%d/%Y}
+ }
+
+ if {$date == "now"} {
+ set seconds [::clock seconds]
+ $itk_component(date) insert end \
+ [clock format $seconds -format "$format" -gmt $itk_option(-gmt)]
+
+ } elseif { $itk_option(-iq) != "low" } {
+ if {[catch {::clock format $date}] == 0} {
+ set seconds $date
+ } elseif {[catch {set seconds [::clock scan $date -gmt \
+ $itk_option(-gmt)]}] != 0} {
+ error "bad date: \"$date\", must be a valid date\
+ string, clock clicks value or the keyword now"
+ }
+ $itk_component(date) insert end \
+ [clock format $seconds -format "$format" -gmt $itk_option(-gmt)]
+ } else {
+ # Note that it doesn't matter what -int is set to.
+ $itk_component(date) insert end $date
+ }
+
+ if {$itk_option(-int)} {
+ _setField year
+ } else {
+ _setField month
+ }
+
+ return
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: isvalid
+#
+# Returns a boolean indication of the validity of the currently
+# displayed date value. For example, 3/3/1960 is valid whereas
+# 02/29/1997 is invalid.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::isvalid {} {
+ if {[catch {clock scan [$itk_component(date) get]}] != 0} {
+ return 0
+ } else {
+ return 1
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _focusIn
+#
+# This method is bound to the <FocusIn> event. It resets the
+# insert cursor and field settings to be back to their last known
+# positions.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::_focusIn {} {
+ _setField $_cfield
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _keyPress
+#
+# This method is the workhorse of the class. It is bound to the
+# <KeyPress> event and controls the processing of all key strokes.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::_keyPress {char sym state} {
+ #
+ # Determine which field we are in currently. This is needed
+ # since the user may have moved to this position via a mouse
+ # selection and so it would not be in the position we last
+ # knew it to be.
+ #
+ _whichField
+
+ #
+ # If we are using an international date the split char is "-"
+ # otherwise it is "/".
+ #
+ if {$itk_option(-int)} {
+ set split_char "-"
+ } else {
+ set split_char "/"
+ }
+
+
+ #
+ # Set up a few basic variables we'll be needing throughout the
+ # rest of the method such as the position of the insert cursor
+ # and the currently displayed day, month, and year.
+ #
+ set icursor [$itk_component(date) index insert]
+ set splist [split [$itk_component(date) get] "$split_char"]
+
+
+ # A bunch of added variables to allow for the use of int dates
+ if {$itk_option(-int)} {
+ set order {year month day}
+ set year [lindex $splist 0]
+ set month [lindex $splist 1]
+ set day [lindex $splist 2]
+ set year_start_pos 0
+ set year_second_pos 1
+ set year_third_pos 2
+ set year_fourth_pos 3
+ set year_end_pos 4
+ set month_start_pos 5
+ set month_second_pos 6
+ set month_end_pos 7
+ set day_start_pos 8
+ set day_second_pos 9
+ set day_end_pos 10
+ } else {
+ set order {month day year}
+ set month [lindex $splist 0]
+ set day [lindex $splist 1]
+ set year [lindex $splist 2]
+ set month_start_pos 0
+ set month_second_pos 1
+ set month_end_pos 2
+ set day_start_pos 3
+ set day_second_pos 4
+ set day_end_pos 5
+ set year_start_pos 6
+ set year_second_pos 7
+ set year_third_pos 8
+ set year_fourth_pos 9
+ set year_end_pos 10
+ }
+
+
+ #
+ # Process numeric keystrokes. This involes a fair amount of
+ # processing with step one being to check and make sure we
+ # aren't attempting to insert more that 10 characters. If
+ # so ring the bell and break.
+ #
+ if {[regexp {[0-9]} $char]} {
+ if {[$itk_component(date) index insert] == 10} {
+ bell
+ return -code break
+ }
+
+ #
+ # If we are currently in the month field then we process the
+ # number entered based on the cursor position. If we are at
+ # at the first position and our iq is low, then accept any
+ # input.
+ #
+ if {$_cfield == "month"} {
+
+ if {[$itk_component(date) index insert] == $month_start_pos} {
+ if {$itk_option(-iq) == "low"} {
+ $itk_component(date) delete $month_start_pos
+ $itk_component(date) insert $month_start_pos $char
+ } else {
+ #
+ # Otherwise, we're slightly smarter. If the number
+ # is less than two insert it at position zero. If
+ # this makes the month greater than twelve, set the
+ # number at position one to zero which makes in
+ # effect puts the month back in range.
+ #
+ regsub {([0-9])([0-9])} $month "$char\\2" month2b
+
+ if {$char < 2} {
+ $itk_component(date) delete $month_start_pos
+ $itk_component(date) insert $month_start_pos $char
+
+ if {$month2b > 12} {
+ $itk_component(date) delete $month_second_pos
+ $itk_component(date) insert $month_second_pos 0
+ $itk_component(date) icursor $month_second_pos
+ } elseif {$month2b == "00"} {
+ $itk_component(date) delete $month_second_pos
+ $itk_component(date) insert $month_second_pos 1
+ $itk_component(date) icursor $month_second_pos
+ }
+
+ #
+ # Finally, if the number is greater than one we'll
+ # assume that they really mean to be entering a zero
+ # followed by their number, do so for them, and
+ # proceed to skip to the next field which is the
+ # day field.
+ #
+ } else {
+ $itk_component(date) delete $month_start_pos $month_end_pos
+ $itk_component(date) insert $month_start_pos 0$char
+ _setField day
+ }
+ }
+
+ #
+ # Else, we're at the second month position. Again, if we aren't
+ # too smart, let them enter anything. Otherwise, if the
+ # number makes the month exceed twelve, set the month to
+ # zero followed by their number to get it back into range.
+ #
+ } else {
+ regsub {([0-9])([0-9])} $month "\\1$char" month2b
+
+ if {$itk_option(-iq) == "low"} {
+ $itk_component(date) delete $month_second_pos
+ $itk_component(date) insert $month_second_pos $char
+ } else {
+ if {$month2b > 12} {
+ $itk_component(date) delete $month_start_pos $month_end_pos
+ $itk_component(date) insert $month_start_pos 0$char
+ } elseif {$month2b == "00"} {
+ bell
+ return -code break
+ } else {
+ $itk_component(date) delete $month_second_pos
+ $itk_component(date) insert $month_second_pos $char
+ }
+ }
+ _setField day
+ }
+
+ #
+ # Now, the month processing is complete and if we're of a
+ # high level of intelligence, then we'll make sure that the
+ # current value for the day is valid for this month. If
+ # it is beyond the last day for this month, change it to
+ # be the last day of the new month.
+ #
+ if {$itk_option(-iq) == "high"} {
+ set splist [split [$itk_component(date) get] "$split_char"]
+ set month [lindex $splist [lsearch $order month]]
+ if {$day > [set endday [_lastDay $month $year]]} {
+ set icursor [$itk_component(date) index insert]
+ $itk_component(date) delete $day_start_pos $day_end_pos
+ $itk_component(date) insert $day_start_pos $endday
+ $itk_component(date) icursor $icursor
+ }
+ }
+
+ #
+ # Finally, return with a code of break to stop any normal
+ # processing in that we've done all that is necessary.
+ #
+ return -code break
+ }
+
+ #
+ # This next block of code is for processing of the day field
+ # which is quite similar is strategy to that of the month.
+ #
+ if {$_cfield == "day"} {
+ if {$itk_option(-iq) == "high"} {
+ set endofMonth [_lastDay $month $year]
+ } else {
+ set endofMonth 31
+ }
+
+ #
+ # If we are at the first cursor position for the day
+ # we are processing
+ # the first character of the day field. If we have an iq
+ # of low accept any input.
+ #
+ if {[$itk_component(date) index insert] == $day_start_pos} {
+ if {$itk_option(-iq) == "low"} {
+ $itk_component(date) delete $day_start_pos
+ $itk_component(date) insert $day_start_pos $char
+
+ } else {
+
+ #
+ # If the day to be is double zero, then make the
+ # day be the first.
+ #
+ regsub {([0-9])([0-9])} $day "$char\\2" day2b
+
+ if {$day2b == "00"} {
+ $itk_component(date) delete $day_start_pos $day_end_pos
+ $itk_component(date) insert $day_start_pos 01
+ $itk_component(date) icursor $day_second_pos
+ #
+ # Otherwise, if the character is less than four
+ # and the month is not Feburary, insert the number
+ # and if this makes the day be beyond the valid
+ # range for this month, than set to be back in
+ # range.
+ #
+ } elseif {($char < 4) && ($month != "02")} {
+ $itk_component(date) delete $day_start_pos
+ $itk_component(date) insert $day_start_pos $char
+
+ if {$day2b > $endofMonth} {
+ $itk_component(date) delete $day_second_pos
+ $itk_component(date) insert $day_second_pos 0
+ $itk_component(date) icursor $day_second_pos
+ }
+
+ #
+ # For Feburary with a number to be entered of
+ # less than three, make sure the number doesn't
+ # make the day be greater than the correct range
+ # and if so adjust the input.
+ #
+ } elseif {$char < 3} {
+ $itk_component(date) delete $day_start_pos
+ $itk_component(date) insert $day_start_pos $char
+ if {$day2b > $endofMonth} {
+ $itk_component(date) delete $day_start_pos $day_end_pos
+ $itk_component(date) insert $day_start_pos $endofMonth
+ $itk_component(date) icursor $day_second_pos
+ }
+
+ #
+ # Finally, if the number is greater than three,
+ # set the day to be zero followed by the number
+ # entered and proceed to the year field or end.
+ #
+ } else {
+ $itk_component(date) delete $day_start_pos $day_end_pos
+ $itk_component(date) insert $day_start_pos 0$char
+ $itk_component(date) icursor $day_end_pos
+ if {!$itk_option(-int)} {
+ _setField year
+ }
+ }
+ }
+ #
+ # Else, we're dealing with the second number in the day
+ # field. If we're not too bright accept anything, otherwise
+ # if the day is beyond the range for this month or equal to
+ # zero then ring the bell.
+ #
+ } else {
+ regsub {([0-9])([0-9])} $day "\\1$char" day2b
+
+ if {($itk_option(-iq) != "low") && \
+ (($day2b > $endofMonth) || ($day2b == "00"))} {
+ bell
+ } else {
+ $itk_component(date) delete $day_second_pos
+ $itk_component(date) insert $day_second_pos $char
+ $itk_component(date) icursor $day_end_pos
+ if {!$itk_option(-int)} {
+ _setField year
+ }
+ }
+ }
+
+ #
+ # Return with a code of break to prevent normal processing.
+ #
+ return -code break
+ }
+
+ #
+ # This month and day we're tough, the code for the year is
+ # comparitively simple. Accept any input and if we are really
+ # sharp, then make sure the day is correct for the month
+ # given the year. In short, handle leap years.
+ #
+ if {$_cfield == "year"} {
+ if {$itk_option(-iq) == "low"} {
+ $itk_component(date) delete $icursor
+ $itk_component(date) insert $icursor $char
+ } else {
+ set prevdate [get]
+ if {[$itk_component(date) index insert] == $year_start_pos} {
+ set yrdgt [lindex [split [lindex \
+ [split $prevdate "$split_char"] [lsearch $order year]] ""] 0]
+ if {$char != $yrdgt} {
+ if {$char == 1} {
+ $itk_component(date) delete $icursor $year_end_pos
+ $itk_component(date) insert $icursor 1999
+ } elseif {$char == 2} {
+ $itk_component(date) delete $icursor $year_end_pos
+ $itk_component(date) insert $icursor 2000
+ } else {
+ bell
+ return -code break
+ }
+ }
+
+ $itk_component(date) icursor $year_second_pos
+ return -code break
+ }
+
+ $itk_component(date) delete $icursor
+ $itk_component(date) insert $icursor $char
+
+
+ if {[catch {clock scan [get]}] != 0} {
+ $itk_component(date) delete $year_start_pos $year_end_pos
+ $itk_component(date) insert $year_start_pos \
+ [lindex [split $prevdate "$split_char"] [lsearch $order year]]
+ $itk_component(date) icursor $icursor
+
+ bell
+ return -code break
+ }
+
+ if {$itk_option(-iq) == "high"} {
+ set splist [split [$itk_component(date) get] "$split_char"]
+ set year [lindex $splist [lsearch $order year]]
+
+ if {$day > [set endday [_lastDay $month $year]]} {
+ set icursor [$itk_component(date) index insert]
+ $itk_component(date) delete $day_start_pos $day_end_pos
+ $itk_component(date) insert $day_start_pos $endday
+ $itk_component(date) icursor $icursor
+ }
+ }
+ }
+ if {$itk_option(-int)} {
+ if {$icursor == $year_fourth_pos } {
+ _setField month
+ }
+ }
+ return -code break
+ }
+
+ #
+ # Process the plus and the up arrow keys. They both yeild the same
+ # effect, they increment the day by one.
+ #
+ } elseif {($sym == "plus") || ($sym == "Up")} {
+ if {[catch {show [clock scan "1 day" -base [get -clicks]]}] != 0} {
+ bell
+ }
+ return -code break
+
+ #
+ # Process the minus and the down arrow keys which decrement the day.
+ #
+ } elseif {($sym == "minus") || ($sym == "Down")} {
+ if {[catch {show [clock scan "-1 day" -base [get -clicks]]}] != 0} {
+ bell
+ }
+ return -code break
+
+ #
+ # A tab key moves the day/month/year (or year/month/day) field
+ # forward by one unless
+ # the current field is the last field. In that case we'll let tab
+ # do what is supposed to and pass the focus onto the next widget.
+ #
+ } elseif {($sym == "Tab") && ($state == 0)} {
+ if {$_cfield != "[lindex $order 2]"} {
+ _moveField forward
+ return -code break
+ } else {
+ _setField "[lindex $order 0]"
+ return -code continue
+ }
+
+ #
+ # A ctrl-tab key moves the day/month/year field backwards by one
+ # unless the current field is the the first field. In that case we'll
+ # let tab take the focus to a previous widget.
+ #
+ } elseif {($sym == "Tab") && ($state == 4)} {
+ if {$_cfield != "[lindex $order 0]"} {
+ _moveField backward
+ return -code break
+ } else {
+ set _cfield "[lindex $order 0]"
+ return -code continue
+ }
+
+ #
+ # A right arrow key moves the insert cursor to the right one.
+ #
+ } elseif {$sym == "Right"} {
+ _forward
+ return -code break
+
+ #
+ # A left arrow, backspace, or delete key moves the insert cursor
+ # to the left one. This is what you expect for the left arrow
+ # and since the whole widget always operates in overstrike mode,
+ # it makes the most sense for backspace and delete to do the same.
+ #
+ } elseif {$sym == "Left" || $sym == "BackSpace" || $sym == "Delete"} {
+ _backward
+ return -code break
+
+ } elseif {($sym == "Control_L") || ($sym == "Shift_L") || \
+ ($sym == "Control_R") || ($sym == "Shift_R")} {
+ return -code break
+
+ #
+ # A Return key invokes the optionally specified command option.
+ #
+ } elseif {$sym == "Return"} {
+ uplevel #0 $itk_option(-command)
+ return -code break
+ } else {
+ bell
+ return -code break
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _setField field
+#
+# Internal method which adjusts the field to be that of the
+# argument, setting the insert cursor appropriately.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::_setField {field} {
+ set _cfield $field
+
+ if {$itk_option(-int)} {
+ set year_pos 2
+ set month_pos 5
+ set day_pos 8
+ } else {
+ set month_pos 0
+ set day_pos 3
+ set year_pos 8
+ }
+
+
+ switch $field {
+ "month" {
+ $itk_component(date) icursor $month_pos
+ }
+ "day" {
+ $itk_component(date) icursor $day_pos
+ }
+ "year" {
+ $itk_component(date) icursor $year_pos
+ }
+ default {
+ error "bad field: \"$field\", must be month, day or year"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _moveField
+#
+# Internal method for moving the field forward or backward by one.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::_moveField {direction} {
+
+ set index [lsearch $_fields $_cfield]
+
+ if {$direction == "forward"} {
+ set newIndex [expr {$index + 1}]
+ } else {
+ set newIndex [expr {$index - 1}]
+ }
+
+ if {$newIndex == [llength $_fields]} {
+ set newIndex 0
+ }
+ if {$newIndex < 0} {
+ set newIndex [expr {[llength $_fields] - 1}]
+ }
+
+ _setField [lindex $_fields $newIndex]
+
+ return
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _whichField
+#
+# Internal method which returns the current field that the cursor
+# is currently within.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::_whichField {} {
+ set icursor [$itk_component(date) index insert]
+
+ if {$itk_option(-int)} {
+ switch $icursor {
+ 0 - 1 - 2 - 3 {
+ set _cfield "year"
+ }
+ 5 - 6 {
+ set _cfield "month"
+ }
+ 8 - 9 {
+ set _cfield "day"
+ }
+ }
+ } else {
+ switch $icursor {
+ 0 - 1 {
+ set _cfield "month"
+ }
+ 3 - 4 {
+ set _cfield "day"
+ }
+ 6 - 7 - 8 - 9 {
+ set _cfield "year"
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _forward
+#
+# Internal method which moves the cursor forward by one character
+# jumping over the slashes and wrapping.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::_forward {} {
+ set icursor [$itk_component(date) index insert]
+
+ if {$itk_option(-int)} {
+ switch $icursor {
+ 3 {
+ _setField month
+ }
+ 6 {
+ _setField day
+ }
+ 9 - 10 {
+ _setField year
+ }
+ default {
+ $itk_component(date) icursor [expr {$icursor + 1}]
+ }
+ }
+ } else {
+ switch $icursor {
+ 1 {
+ _setField day
+ }
+ 4 {
+ _setField year
+ }
+ 9 - 10 {
+ _setField month
+ }
+ default {
+ $itk_component(date) icursor [expr {$icursor + 1}]
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _backward
+#
+# Internal method which moves the cursor backward by one character
+# jumping over the slashes and wrapping.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::_backward {} {
+ set icursor [$itk_component(date) index insert]
+ if {$itk_option(-int)} {
+ switch $icursor {
+ 8 {
+ _setField month
+ }
+ 5 {
+ _setField year
+ }
+ 0 {
+ _setField day
+ }
+ default {
+ $itk_component(date) icursor [expr {$icursor -1}]
+ }
+ }
+ } else {
+ switch $icursor {
+ 6 {
+ _setField day
+ }
+ 3 {
+ _setField month
+ }
+ 0 {
+ _setField year
+ }
+ default {
+ $itk_component(date) icursor [expr {$icursor -1}]
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _lastDay month year
+#
+# Internal method which determines the last day of the month for
+# the given month and year. We start at 28 and go forward till
+# we fail. Crude but effective.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Datefield::_lastDay {month year} {
+ set lastone 28
+
+ for {set lastone 28} {$lastone < 32} {incr lastone} {
+ set nextone [expr $lastone + 1]
+ if {[catch {clock scan $month/$nextone/$year}] != 0} {
+ return $lastone
+ }
+ }
+}
diff --git a/iwidgets/generic/dialog.itk b/iwidgets/generic/dialog.itk
new file mode 100644
index 00000000000..667d46d1924
--- /dev/null
+++ b/iwidgets/generic/dialog.itk
@@ -0,0 +1,92 @@
+#
+# Dialog
+# ----------------------------------------------------------------------
+# Implements a standard dialog box providing standard buttons and a
+# child site for use in derived classes. The buttons include ok, apply,
+# cancel, and help. Options exist to configure the buttons.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Dialog {
+ keep -background -cursor -foreground -modality
+}
+
+# ------------------------------------------------------------------
+# DIALOG
+# ------------------------------------------------------------------
+itcl::class iwidgets::Dialog {
+ inherit iwidgets::Dialogshell
+
+ constructor {args} {}
+}
+
+#
+# Provide a lowercased access method for the Dialog class.
+#
+proc ::iwidgets::dialog {pathName args} {
+ uplevel ::iwidgets::Dialog $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Dialog.master "." widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialog::constructor {args} {
+ #
+ # Add the standard buttons: OK, Apply, Cancel, and Help, making
+ # OK be the default button.
+ #
+ add OK -text OK -command [itcl::code $this deactivate 1]
+ add Apply -text Apply
+ add Cancel -text Cancel -command [itcl::code $this deactivate 0]
+ add Help -text Help
+
+ default OK
+
+ #
+ # Bind the window manager delete protocol to invocation of the
+ # cancel button. This can be overridden by the user via the
+ # execution of a similar command outside the class.
+ #
+ wm protocol $itk_component(hull) WM_DELETE_WINDOW \
+ [itcl::code $this invoke Cancel]
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
diff --git a/iwidgets/generic/dialogshell.itk b/iwidgets/generic/dialogshell.itk
new file mode 100644
index 00000000000..7284b354db3
--- /dev/null
+++ b/iwidgets/generic/dialogshell.itk
@@ -0,0 +1,350 @@
+# Dialogshell
+# ----------------------------------------------------------------------
+# This class is implements a dialog shell which is a top level widget
+# composed of a button box, separator, and child site area. The class
+# also has methods to control button construction.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Dialogshell {
+ keep -background -cursor -foreground -modality
+}
+
+# ------------------------------------------------------------------
+# DIALOGSHELL
+# ------------------------------------------------------------------
+itcl::class iwidgets::Dialogshell {
+ inherit iwidgets::Shell
+
+ constructor {args} {}
+
+ itk_option define -thickness thickness Thickness 3
+ itk_option define -buttonboxpos buttonBoxPos Position s
+ itk_option define -separator separator Separator on
+ itk_option define -padx padX Pad 10
+ itk_option define -pady padY Pad 10
+
+ public method childsite {}
+ public method index {args}
+ public method add {args}
+ public method insert {args}
+ public method delete {args}
+ public method hide {args}
+ public method show {args}
+ public method default {args}
+ public method invoke {args}
+ public method buttonconfigure {args}
+ public method buttoncget {index option}
+}
+
+#
+# Provide a lowercased access method for the Dialogshell class.
+#
+proc ::iwidgets::dialogshell {pathName args} {
+ uplevel ::iwidgets::Dialogshell $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Dialogshell.master "." widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::constructor {args} {
+ itk_option remove iwidgets::Shell::padx iwidgets::Shell::pady
+
+ #
+ # Create the user child site, separator, and button box,
+ #
+ itk_component add -protected dschildsite {
+ frame $itk_interior.dschildsite
+ }
+
+ itk_component add separator {
+ frame $itk_interior.separator -relief sunken
+ }
+
+ itk_component add bbox {
+ iwidgets::Buttonbox $itk_interior.bbox
+ } {
+ usual
+
+ rename -padx -buttonboxpadx buttonBoxPadX Pad
+ rename -pady -buttonboxpady buttonBoxPadY Pad
+ }
+
+ #
+ # Set the itk_interior variable to be the childsite for derived
+ # classes.
+ #
+ set itk_interior $itk_component(dschildsite)
+
+ #
+ # Set up the default button so that if <Return> is pressed in
+ # any widget, it will invoke the default button.
+ #
+ bind $itk_component(hull) <Return> [itcl::code $this invoke]
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -thickness
+#
+# Specifies the thickness of the separator. It sets the width and
+# height of the separator to the thickness value and the borderwidth
+# to half the thickness.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Dialogshell::thickness {
+ $itk_component(separator) config -height $itk_option(-thickness)
+ $itk_component(separator) config -width $itk_option(-thickness)
+ $itk_component(separator) config \
+ -borderwidth [expr {$itk_option(-thickness) / 2}]
+}
+
+# ------------------------------------------------------------------
+# OPTION: -buttonboxpos
+#
+# Specifies the position of the button box relative to the child site.
+# The separator appears between the child site and button box.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Dialogshell::buttonboxpos {
+ set parent [winfo parent $itk_component(bbox)]
+
+ switch $itk_option(-buttonboxpos) {
+ n {
+ $itk_component(bbox) configure -orient horizontal
+
+ grid $itk_component(bbox) -row 0 -column 0 -sticky ew
+ grid $itk_component(separator) -row 1 -column 0 -sticky ew
+ grid $itk_component(dschildsite) -row 2 -column 0 -sticky nsew
+
+ grid rowconfigure $parent 0 -weight 0
+ grid rowconfigure $parent 1 -weight 0
+ grid rowconfigure $parent 2 -weight 1
+ grid columnconfigure $parent 0 -weight 1
+ grid columnconfigure $parent 1 -weight 0
+ grid columnconfigure $parent 2 -weight 0
+ }
+ s {
+ $itk_component(bbox) configure -orient horizontal
+
+ grid $itk_component(dschildsite) -row 0 -column 0 -sticky nsew
+ grid $itk_component(separator) -row 1 -column 0 -sticky ew
+ grid $itk_component(bbox) -row 2 -column 0 -sticky ew
+
+ grid rowconfigure $parent 0 -weight 1
+ grid rowconfigure $parent 1 -weight 0
+ grid rowconfigure $parent 2 -weight 0
+ grid columnconfigure $parent 0 -weight 1
+ grid columnconfigure $parent 1 -weight 0
+ grid columnconfigure $parent 2 -weight 0
+ }
+ w {
+ $itk_component(bbox) configure -orient vertical
+
+ grid $itk_component(bbox) -row 0 -column 0 -sticky ns
+ grid $itk_component(separator) -row 0 -column 1 -sticky ns
+ grid $itk_component(dschildsite) -row 0 -column 2 -sticky nsew
+
+ grid rowconfigure $parent 0 -weight 1
+ grid rowconfigure $parent 1 -weight 0
+ grid rowconfigure $parent 2 -weight 0
+ grid columnconfigure $parent 0 -weight 0
+ grid columnconfigure $parent 1 -weight 0
+ grid columnconfigure $parent 2 -weight 1
+ }
+ e {
+ $itk_component(bbox) configure -orient vertical
+
+ grid $itk_component(dschildsite) -row 0 -column 0 -sticky nsew
+ grid $itk_component(separator) -row 0 -column 1 -sticky ns
+ grid $itk_component(bbox) -row 0 -column 2 -sticky ns
+
+ grid rowconfigure $parent 0 -weight 1
+ grid rowconfigure $parent 1 -weight 0
+ grid rowconfigure $parent 2 -weight 0
+ grid columnconfigure $parent 0 -weight 1
+ grid columnconfigure $parent 1 -weight 0
+ grid columnconfigure $parent 2 -weight 0
+ }
+ default {
+ error "bad buttonboxpos option\
+ \"$itk_option(-buttonboxpos)\": should be n,\
+ s, e, or w"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -separator
+#
+# Boolean option indicating wheather to display the separator.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Dialogshell::separator {
+ if {$itk_option(-separator)} {
+ $itk_component(separator) configure -relief sunken
+ } else {
+ $itk_component(separator) configure -relief flat
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -padx
+#
+# Specifies a padding distance for the childsite in the X-direction.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Dialogshell::padx {
+ grid configure $itk_component(dschildsite) -padx $itk_option(-padx)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -pady
+#
+# Specifies a padding distance for the childsite in the Y-direction.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Dialogshell::pady {
+ grid configure $itk_component(dschildsite) -pady $itk_option(-pady)
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Return the pathname of the user accessible area.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::childsite {} {
+ return $itk_component(dschildsite)
+}
+
+# ------------------------------------------------------------------
+# METHOD: index index
+#
+# Thin wrapper of Buttonbox's index method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::index {args} {
+ uplevel $itk_component(bbox) index $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: add tag ?option value ...?
+#
+# Thin wrapper of Buttonbox's add method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::add {args} {
+ uplevel $itk_component(bbox) add $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert index tag ?option value ...?
+#
+# Thin wrapper of Buttonbox's insert method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::insert {args} {
+ uplevel $itk_component(bbox) insert $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete tag
+#
+# Thin wrapper of Buttonbox's delete method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::delete {args} {
+ uplevel $itk_component(bbox) delete $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: hide index
+#
+# Thin wrapper of Buttonbox's hide method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::hide {args} {
+ uplevel $itk_component(bbox) hide $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: show index
+#
+# Thin wrapper of Buttonbox's show method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::show {args} {
+ uplevel $itk_component(bbox) show $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: default index
+#
+# Thin wrapper of Buttonbox's default method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::default {args} {
+ uplevel $itk_component(bbox) default $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: invoke ?index?
+#
+# Thin wrapper of Buttonbox's invoke method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::invoke {args} {
+ uplevel $itk_component(bbox) invoke $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: buttonconfigure index ?option? ?value option value ...?
+#
+# Thin wrapper of Buttonbox's buttonconfigure method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::buttonconfigure {args} {
+ uplevel $itk_component(bbox) buttonconfigure $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: buttoncget index option
+#
+# Thin wrapper of Buttonbox's buttoncget method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Dialogshell::buttoncget {index option} {
+ uplevel $itk_component(bbox) buttoncget [list $index] \
+ [list $option]
+}
diff --git a/iwidgets/generic/disjointlistbox.itk b/iwidgets/generic/disjointlistbox.itk
new file mode 100644
index 00000000000..c32331a3f83
--- /dev/null
+++ b/iwidgets/generic/disjointlistbox.itk
@@ -0,0 +1,529 @@
+#
+# ::iwidgets::Disjointlistbox
+# ----------------------------------------------------------------------
+# Implements a widget which maintains a disjoint relationship between
+# the items displayed by two listboxes. The disjointlistbox is composed
+# of 2 Scrolledlistboxes, 2 Pushbuttons, and 2 labels.
+#
+# The disjoint behavior of this widget exists between the two Listboxes,
+# That is, a given instance of a ::iwidgets::Disjointlistbox will never
+# exist which has Listbox widgets with items in common.
+#
+# Users may transfer items between the two Listbox widgets using the
+# the two Pushbuttons.
+#
+# The options include the ability to configure the "items" displayed by
+# either of the two Listboxes and to control the placement of the insertion
+# and removal buttons.
+#
+# The following depicts the allowable "-buttonplacement" option values
+# and their associated layout:
+#
+# "-buttonplacement" => center
+#
+# --------------------------
+# |listbox| |listbox|
+# | |________| |
+# | (LHS) | button | (RHS) |
+# | |========| |
+# | | button | |
+# |_______|--------|_______|
+# | count | | count |
+# --------------------------
+#
+# "-buttonplacement" => bottom
+#
+# ---------------------
+# | listbox | listbox |
+# | (LHS) | (RHS) |
+# |_________|_________|
+# | button | button |
+# |---------|---------|
+# | count | count |
+# ---------------------
+#
+# ----------------------------------------------------------------------
+# AUTHOR: John A. Tucker EMAIL: jatucker@spd.dsccc.com
+#
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Disjointlistbox.lhsLabelText Available widgetDefault
+option add *Disjointlistbox.rhsLabelText Current widgetDefault
+option add *Disjointlistbox.lhsButtonLabel {Insert >>} widgetDefault
+option add *Disjointlistbox.rhsButtonLabel {<< Remove} widgetDefault
+option add *Disjointlistbox.vscrollMode static widgetDefault
+option add *Disjointlistbox.hscrollMode static widgetDefault
+option add *Disjointlistbox.selectMode multiple widgetDefault
+option add *Disjointlistbox.labelPos nw widgetDefault
+option add *Disjointlistbox.buttonPlacement bottom widgetDefault
+option add *Disjointlistbox.lhsSortOption increasing widgetDefault
+option add *Disjointlistbox.rhsSortOption increasing widgetDefault
+
+
+#
+# Usual options.
+#
+itk::usual Disjointlistbox {
+ keep -background -textbackground -cursor \
+ -foreground -textfont -labelfont
+}
+
+
+# ----------------------------------------------------------------------
+# ::iwidgets::Disjointlistbox
+# ----------------------------------------------------------------------
+itcl::class ::iwidgets::Disjointlistbox {
+
+ inherit itk::Widget
+
+ #
+ # options
+ #
+ itk_option define -buttonplacement buttonPlacement ButtonPlacement bottom
+ itk_option define -lhsbuttonlabel lhsButtonLabel LabelText {Insert >>}
+ itk_option define -rhsbuttonlabel rhsButtonLabel LabelText {<< Remove}
+ itk_option define -lhssortoption lhsSortOption LhsSortOption increasing
+ itk_option define -rhssortoption rhsSortOption RhsSortOption increasing
+
+ constructor {args} {}
+
+ #
+ # PUBLIC
+ #
+ public {
+ method clear {}
+ method getlhs {{first 0} {last end}}
+ method getrhs {{first 0} {last end}}
+ method lhs {args}
+ method insertlhs {items}
+ method insertrhs {items}
+ method setlhs {items}
+ method setrhs {items}
+ method rhs {args}
+ }
+
+ #
+ # PROTECTED
+ #
+ protected {
+ method insert {theListbox items}
+ method listboxClick {clickSide otherSide}
+ method listboxDblClick {clickSide otherSide}
+ method remove {theListbox items}
+ method showCount {}
+ method transfer {}
+
+ variable sourceListbox {}
+ variable destinationListbox {}
+ }
+}
+
+#
+# Provide a lowercased access method for the ::iwidgets::Disjointlistbox class.
+#
+proc ::iwidgets::disjointlistbox {pathName args} {
+ uplevel ::iwidgets::Disjointlistbox $pathName $args
+}
+
+# ------------------------------------------------------------------
+#
+# Method: Constructor
+#
+# Purpose:
+#
+itcl::body ::iwidgets::Disjointlistbox::constructor {args} {
+ #
+ # Create the left-most Listbox
+ #
+ itk_component add lhs {
+ iwidgets::Scrolledlistbox $itk_interior.lhs \
+ -selectioncommand [itcl::code $this listboxClick lhs rhs] \
+ -dblclickcommand [itcl::code $this listboxDblClick lhs rhs]
+ } {
+ usual
+ keep -selectmode -vscrollmode -hscrollmode
+ rename -labeltext -lhslabeltext lhsLabelText LabelText
+ }
+
+ #
+ # Create the right-most Listbox
+ #
+ itk_component add rhs {
+ iwidgets::Scrolledlistbox $itk_interior.rhs \
+ -selectioncommand [itcl::code $this listboxClick rhs lhs] \
+ -dblclickcommand [itcl::code $this listboxDblClick rhs lhs]
+ } {
+ usual
+ keep -selectmode -vscrollmode -hscrollmode
+ rename -labeltext -rhslabeltext rhsLabelText LabelText
+ }
+
+ #
+ # Create the left-most item count Label
+ #
+ itk_component add lhsCount {
+ label $itk_interior.lhscount
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ #
+ # Create the right-most item count Label
+ #
+ itk_component add rhsCount {
+ label $itk_interior.rhscount
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ set sourceListbox $itk_component(lhs)
+ set destinationListbox $itk_component(rhs)
+
+ #
+ # Bind the "showCount" method to the Map event of one of the labels
+ # to keep the diplayed item count current.
+ #
+ bind $itk_component(lhsCount) <Map> [itcl::code $this showCount]
+
+ grid $itk_component(lhs) -row 0 -column 0 -sticky nsew
+ grid $itk_component(rhs) -row 0 -column 2 -sticky nsew
+
+ grid rowconfigure $itk_interior 0 -weight 1
+ grid columnconfigure $itk_interior 0 -weight 1
+ grid columnconfigure $itk_interior 2 -weight 1
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# Method: listboxClick
+#
+# Purpose: Evaluate a single click make in the specified Listbox.
+#
+itcl::body ::iwidgets::Disjointlistbox::listboxClick {clickSide otherSide} {
+ set button "button"
+ $itk_component($clickSide$button) configure -state active
+ $itk_component($otherSide$button) configure -state disabled
+ set sourceListbox $clickSide
+ set destinationListbox $otherSide
+}
+
+# ------------------------------------------------------------------
+# Method: listboxDblClick
+#
+# Purpose: Evaluate a double click in the specified Listbox.
+#
+itcl::body ::iwidgets::Disjointlistbox::listboxDblClick {clickSide otherSide} {
+ listboxClick $clickSide $otherSide
+ transfer
+}
+
+# ------------------------------------------------------------------
+# Method: transfer
+#
+# Purpose: Transfer source Listbox items to destination Listbox
+#
+itcl::body ::iwidgets::Disjointlistbox::transfer {} {
+
+ if {[$sourceListbox selecteditemcount] == 0} {
+ return
+ }
+ set selectedindices [lsort -integer -decreasing [$sourceListbox curselection]]
+ set selecteditems [$sourceListbox getcurselection]
+
+ foreach index $selectedindices {
+ $sourceListbox delete $index
+ }
+
+ foreach item $selecteditems {
+ $destinationListbox insert end $item
+ }
+
+ if {![string equal $itk_option(-${destinationListbox}sortoption) "none"]} {
+ $destinationListbox sort $itk_option(-${destinationListbox}sortoption)
+ }
+
+ showCount
+}
+
+# ------------------------------------------------------------------
+# Method: getlhs
+#
+# Purpose: Retrieve the items of the left Listbox widget
+#
+itcl::body ::iwidgets::Disjointlistbox::getlhs {{first 0} {last end}} {
+ return [lhs get $first $last]
+}
+
+# ------------------------------------------------------------------
+# Method: getrhs
+#
+# Purpose: Retrieve the items of the right Listbox widget
+#
+itcl::body ::iwidgets::Disjointlistbox::getrhs {{first 0} {last end}} {
+ return [rhs get $first $last]
+}
+
+# ------------------------------------------------------------------
+# Method: insertrhs
+#
+# Purpose: Insert items into the right Listbox widget
+#
+itcl::body ::iwidgets::Disjointlistbox::insertrhs {items} {
+ remove $itk_component(lhs) $items
+ insert rhs $items
+}
+
+# ------------------------------------------------------------------
+# Method: insertlhs
+#
+# Purpose: Insert items into the left Listbox widget
+#
+itcl::body ::iwidgets::Disjointlistbox::insertlhs {items} {
+ remove $itk_component(rhs) $items
+ insert lhs $items
+}
+
+# ------------------------------------------------------------------
+# Method: clear
+#
+# Purpose: Remove the items from the Listbox widgets and set the item count
+# Labels text to 0
+#
+itcl::body ::iwidgets::Disjointlistbox::clear {} {
+ lhs clear
+ rhs clear
+ showCount
+}
+
+# ------------------------------------------------------------------
+# Method: insert
+#
+# Purpose: Insert the input items into the input Listbox widget while
+# maintaining the disjoint property between them.
+#
+itcl::body ::iwidgets::Disjointlistbox::insert {theListbox items} {
+
+ set curritems [$theListbox get 0 end]
+
+ foreach item $items {
+ #
+ # if the item is not already present in the Listbox then insert it
+ #
+ if {[lsearch -exact $curritems $item] == -1} {
+ $theListbox insert end $item
+ }
+ }
+
+ if {![string equal $itk_option(-${theListbox}sortoption) "none"]} {
+ $theListbox sort $itk_option(-${theListbox}sortoption)
+ }
+
+ showCount
+}
+
+# ------------------------------------------------------------------
+# Method: remove
+#
+# Purpose: Remove the input items from the input Listbox widget while
+# maintaining the disjoint property between them.
+#
+itcl::body ::iwidgets::Disjointlistbox::remove {theListbox items} {
+
+ set indexes {}
+ set curritems [$theListbox get 0 end]
+
+ foreach item $items {
+ #
+ # if the item is in the listbox then add its index to the index list
+ #
+ if {[set index [lsearch -exact $curritems $item]] != -1} {
+ lappend indexes $index
+ }
+ }
+
+ foreach index [lsort -integer -decreasing $indexes] {
+ $theListbox delete $index
+ }
+ showCount
+}
+
+# ------------------------------------------------------------------
+# Method: showCount
+#
+# Purpose: Set the text of the item count Labels.
+#
+itcl::body ::iwidgets::Disjointlistbox::showCount {} {
+ $itk_component(lhsCount) config -text "item count: [lhs size]"
+ $itk_component(rhsCount) config -text "item count: [rhs size]"
+}
+
+# ------------------------------------------------------------------
+# METHOD: setlhs
+#
+# Set the items of the left-most Listbox with the input list
+# option. Remove all (if any) items from the right-most Listbox
+# which exist in the input list option to maintain the disjoint
+# property between the two
+#
+itcl::body ::iwidgets::Disjointlistbox::setlhs {items} {
+ lhs clear
+ insertlhs $items
+}
+
+# ------------------------------------------------------------------
+# METHOD: setrhs
+#
+# Set the items of the right-most Listbox with the input list
+# option. Remove all (if any) items from the left-most Listbox
+# which exist in the input list option to maintain the disjoint
+# property between the two
+#
+itcl::body ::iwidgets::Disjointlistbox::setrhs {items} {
+ rhs clear
+ insertrhs $items
+}
+
+# ------------------------------------------------------------------
+# Method: lhs
+#
+# Purpose: Evaluates the specified arguments against the lhs Listbox
+#
+itcl::body ::iwidgets::Disjointlistbox::lhs {args} {
+ return [eval $itk_component(lhs) $args]
+}
+
+# ------------------------------------------------------------------
+# Method: rhs
+#
+# Purpose: Evaluates the specified arguments against the rhs Listbox
+#
+itcl::body ::iwidgets::Disjointlistbox::rhs {args} {
+ return [eval $itk_component(rhs) $args]
+}
+
+# ------------------------------------------------------------------
+# OPTION: buttonplacement
+#
+# Configure the placement of the buttons to be either between or below
+# the two list boxes.
+#
+itcl::configbody ::iwidgets::Disjointlistbox::buttonplacement {
+ if {$itk_option(-buttonplacement) != ""} {
+
+ if { [lsearch [component] lhsbutton] != -1 } {
+ eval destroy $itk_component(rhsbutton) $itk_component(lhsbutton)
+ }
+
+ if { [lsearch [component] bbox] != -1 } {
+ destroy $itk_component(bbox)
+ }
+
+ set where $itk_option(-buttonplacement)
+
+ switch $where {
+
+ center {
+ #
+ # Create the button box frame
+ #
+ itk_component add bbox {
+ frame $itk_interior.bbox
+ }
+
+ itk_component add lhsbutton {
+ button $itk_component(bbox).lhsbutton -command [itcl::code \
+ $this transfer]
+ } {
+ usual
+ rename -text -lhsbuttonlabel lhsButtonLabel LabelText
+ rename -font -labelfont labelFont Font
+ }
+
+ itk_component add rhsbutton {
+ button $itk_component(bbox).rhsbutton -command [itcl::code \
+ $this transfer]
+ } {
+ usual
+ rename -text -rhsbuttonlabel rhsButtonLabel LabelText
+ rename -font -labelfont labelFont Font
+ }
+
+ grid configure $itk_component(lhsCount) -row 1 -column 0 \
+ -sticky ew
+ grid configure $itk_component(rhsCount) -row 1 -column 2 \
+ -sticky ew
+
+ grid configure $itk_component(bbox) \
+ -in $itk_interior -row 0 -column 1 -columnspan 1 \
+ -sticky nsew
+
+ grid configure $itk_component(rhsbutton) \
+ -in $itk_component(bbox) -row 0 -column 0 -sticky ew
+ grid configure $itk_component(lhsbutton) \
+ -in $itk_component(bbox) -row 1 -column 0 -sticky ew
+ }
+
+ bottom {
+
+ itk_component add lhsbutton {
+ button $itk_interior.lhsbutton -command [itcl::code $this \
+ transfer]
+ } {
+ usual
+ rename -text -lhsbuttonlabel lhsButtonLabel LabelText
+ rename -font -labelfont labelFont Font
+ }
+
+ itk_component add rhsbutton {
+ button $itk_interior.rhsbutton -command [itcl::code $this \
+ transfer]
+ } {
+ usual
+ rename -text -rhsbuttonlabel rhsButtonLabel LabelText
+ rename -font -labelfont labelFont Font
+ }
+
+ grid $itk_component(lhsCount) -row 2 -column 0 -sticky ew
+ grid $itk_component(rhsCount) -row 2 -column 2 -sticky ew
+ grid $itk_component(lhsbutton) -row 1 -column 0 -sticky ew
+ grid $itk_component(rhsbutton) -row 1 -column 2 -sticky ew
+ }
+
+ default {
+ error "bad buttonplacement option\"$where\": should be center\
+ or bottom"
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: lhssortoption
+#
+# Configure the sort option to use for the left side
+#
+itcl::configbody ::iwidgets::Disjointlistbox::lhssortoption {
+
+ if {![string equal $itk_option(-lhssortoption) "none"]} {
+ $itk_component(lhs) sort $itk_option(-lhssortoption)
+ }
+}
+
+
+# ------------------------------------------------------------------
+# OPTION: rhssortoption
+#
+# Configure the sort option to use for the right side
+#
+itcl::configbody ::iwidgets::Disjointlistbox::rhssortoption {
+
+ if {![string equal $itk_option(-rhssortoption) "none"]} {
+ $itk_component(rhs) sort $itk_option(-rhssortoption)
+ }
+}
diff --git a/iwidgets/generic/entryfield.itk b/iwidgets/generic/entryfield.itk
new file mode 100644
index 00000000000..ce95d7bf790
--- /dev/null
+++ b/iwidgets/generic/entryfield.itk
@@ -0,0 +1,603 @@
+#
+# Entryfield
+# ----------------------------------------------------------------------
+# Implements an enhanced text entry widget.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Sue Yockey E-mail: yockey@acm.org
+# Mark L. Ulferts E-mail: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Entryfield {
+ keep -background -borderwidth -cursor -foreground -highlightcolor \
+ -highlightthickness -insertbackground -insertborderwidth \
+ -insertofftime -insertontime -insertwidth -labelfont \
+ -selectbackground -selectborderwidth -selectforeground \
+ -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# ENTRYFIELD
+# ------------------------------------------------------------------
+itcl::class iwidgets::Entryfield {
+ 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 -pasting pasting Behavior 1
+ itk_option define -validate validate Command {}
+
+ 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 {}
+ }
+
+ proc numeric {char} {}
+ proc integer {string} {}
+ proc alphabetic {char} {}
+ proc alphanumeric {char} {}
+ proc hexidecimal {string} {}
+ proc real {string} {}
+
+ protected {
+ method _focusCommand {}
+ method _keyPress {char sym state}
+ }
+
+ private method _peek {char}
+ private method _checkLength {}
+}
+
+#
+# Provide a lowercased access method for the Entryfield class.
+#
+proc ::iwidgets::entryfield {pathName args} {
+ uplevel ::iwidgets::Entryfield $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::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)
+
+ #
+ # Entryfield 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::Entryfield::command {}
+
+# ------------------------------------------------------------------
+# OPTION: -focuscommand
+#
+# Command associated upon detection of focus.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Entryfield::focuscommand {}
+
+# ------------------------------------------------------------------
+# OPTION: -validate
+#
+# Specify a command to executed for the validation of Entryfields.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Entryfield::validate {
+ switch $itk_option(-validate) {
+ {} {
+ set itk_option(-validate) {}
+ }
+ numeric {
+ set itk_option(-validate) "::iwidgets::Entryfield::numeric %c"
+ }
+ integer {
+ set itk_option(-validate) "::iwidgets::Entryfield::integer %P"
+ }
+ hexidecimal {
+ set itk_option(-validate) "::iwidgets::Entryfield::hexidecimal %P"
+ }
+ real {
+ set itk_option(-validate) "::iwidgets::Entryfield::real %P"
+ }
+ alphabetic {
+ set itk_option(-validate) "::iwidgets::Entryfield::alphabetic %c"
+ }
+ alphanumeric {
+ set itk_option(-validate) "::iwidgets::Entryfield::alphanumeric %c"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -invalid
+#
+# Specify a command to executed should the current Entryfield contents
+# be proven invalid.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Entryfield::invalid {}
+
+# ------------------------------------------------------------------
+# OPTION: -pasting
+#
+# Allows the developer to enable and disable pasting into the entry
+# component of the entryfield. This is done to avoid potential stack
+# dumps when using the -validate configuration option. Plus, it's just
+# a good idea to have complete control over what you allow the user
+# to enter into the entryfield.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Entryfield::pasting {
+ set oldtags [bindtags $itk_component(entry)]
+ if {[lindex $oldtags 0] != "pastetag"} {
+ bindtags $itk_component(entry) [linsert $oldtags 0 pastetag]
+ }
+
+ if ($itk_option(-pasting)) {
+ bind pastetag <ButtonRelease-2> [itcl::code $this _checkLength]
+ bind pastetag <Control-v> [itcl::code $this _checkLength]
+ bind pastetag <Insert> [itcl::code $this _checkLength]
+ bind pastetag <KeyPress> {}
+ } else {
+ bind pastetag <ButtonRelease-2> {break}
+ bind pastetag <Control-v> {break}
+ bind pastetag <Insert> {break}
+ bind pastetag <KeyPress> {
+ # Disable function keys > F9.
+ if {[regexp {^F[1,2][0-9]+$} "%K"]} {
+ break
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# 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::Entryfield::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::Entryfield::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"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Returns the path name of the child site widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::childsite {} {
+ return $itk_component(efchildsite)
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Thin wrap of the standard entry widget get method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::get {} {
+ return [$itk_component(entry) get]
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete
+#
+# Thin wrap of the standard entry widget delete method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::delete {args} {
+ return [eval $itk_component(entry) delete $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: icursor
+#
+# Thin wrap of the standard entry widget icursor method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::icursor {args} {
+ return [eval $itk_component(entry) icursor $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: index
+#
+# Thin wrap of the standard entry widget index method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::index {args} {
+ return [eval $itk_component(entry) index $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert
+#
+# Thin wrap of the standard entry widget index method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::insert {args} {
+ return [eval $itk_component(entry) insert $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: scan
+#
+# Thin wrap of the standard entry widget scan method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::scan {args} {
+ return [eval $itk_component(entry) scan $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: selection
+#
+# Thin wrap of the standard entry widget selection method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::selection {args} {
+ return [eval $itk_component(entry) selection $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: xview
+#
+# Thin wrap of the standard entry widget xview method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::xview {args} {
+ return [eval $itk_component(entry) xview $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: clear
+#
+# Delete the current entry contents.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::clear {} {
+ $itk_component(entry) delete 0 end
+ icursor 0
+}
+
+# ------------------------------------------------------------------
+# PROCEDURE: numeric char
+#
+# The numeric procedure validates character input for a given
+# Entryfield to be numeric and returns the result.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::numeric {char} {
+ return [regexp {[0-9]} $char]
+}
+
+# ------------------------------------------------------------------
+# PROCEDURE: integer string
+#
+# The integer procedure validates character input for a given
+# Entryfield to be integer and returns the result.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::integer {string} {
+ return [regexp {^[-+]?[0-9]*$} $string]
+}
+
+# ------------------------------------------------------------------
+# PROCEDURE: alphabetic char
+#
+# The alphabetic procedure validates character input for a given
+# Entryfield to be alphabetic and returns the result.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::alphabetic {char} {
+ return [regexp -nocase {[a-z]} $char]
+}
+
+# ------------------------------------------------------------------
+# PROCEDURE: alphanumeric char
+#
+# The alphanumeric procedure validates character input for a given
+# Entryfield to be alphanumeric and returns the result.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::alphanumeric {char} {
+ return [regexp -nocase {[0-9a-z]} $char]
+}
+
+# ------------------------------------------------------------------
+# PROCEDURE: hexadecimal string
+#
+# The hexidecimal procedure validates character input for a given
+# Entryfield to be hexidecimal and returns the result.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::hexidecimal {string} {
+ return [regexp {^(0x)?[0-9a-fA-F]*$} $string]
+}
+
+# ------------------------------------------------------------------
+# PROCEDURE: real string
+#
+# The real procedure validates character input for a given Entryfield
+# to be real and returns the result.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::real {string} {
+ return [regexp {^[-+]?[0-9]*\.?[0-9]*([0-9]\.?[eE][-+]?[0-9]*)?$} $string]
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _peek char
+#
+# The peek procedure returns the value of the Entryfield with the
+# char inserted at the insert position.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::_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]
+
+ regsub -all {\\} "$char" {\\\\} char
+ 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::Entryfield::_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::Entryfield::_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.
+ #
+ #-----------------------------------------------------------
+ # BUG FIX: csmith (Chad Smith: csmith@adc.com), 3/15/99
+ #-----------------------------------------------------------
+ # The following conditional used to hardcode specific state values, such
+ # as "4" and "8". These values are used to detect <Ctrl>, <Shift>, etc.
+ # key combinations. On the windows platform, the <Alt> key is state
+ # 16, and on the unix platform, the <Alt> key is state 8. All <Ctrl>
+ # and <Alt> combinations should be masked out, regardless of the
+ # <NumLock> or <CapsLock> status, and regardless of platform.
+ #-----------------------------------------------------------
+ set CTRL 4
+ global tcl_platform
+ if {$tcl_platform(platform) == "unix"} {
+ set ALT 8
+ } elseif {$tcl_platform(platform) == "windows"} {
+ set ALT 16
+ } else {
+ # This is something other than UNIX or WINDOWS. Default to the
+ # old behavior (UNIX).
+ set ALT 8
+ }
+ # Thanks to Rolf Schroedter for the following elegant conditional. This
+ # masks out all <Ctrl> and <Alt> key combinations.
+ if {($char == "") || ($state & ($CTRL | $ALT))} {
+ 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
+ }
+ }
+
+ #
+ # The validate option may contain a keyword (numeric, alphabetic),
+ # the name of a procedure, or nothing. The numeric and alphabetic
+ # keywords engage typical base level checks. If a command procedure
+ # is specified, then invoke it with the object and character passed
+ # as arguments. If the validate procedure returns false, then the
+ # invalid procedure is called.
+ #
+ if {$itk_option(-validate) != {}} {
+ set cmd $itk_option(-validate)
+
+ regsub -all "%W" "$cmd" $itk_component(hull) cmd
+ regsub -all "%P" "$cmd" [list [_peek $char]] cmd
+ regsub -all "%S" "$cmd" [list [get]] cmd
+ regsub -all "%c" "$cmd" [list $char] cmd
+ regsub -all {\\} "$cmd" {\\\\} cmd
+
+ set valid [uplevel #0 $cmd]
+
+ if {($valid == "") || ([regexp 0|false|off|no $valid])} {
+ uplevel #0 $itk_option(-invalid)
+ return -code break 0
+ }
+ }
+
+ return -code continue 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _checkLength
+#
+# This method was added by csmith for SF ticket 227912. We need to
+# to check the clipboard content before allowing any pasting into
+# the entryfield to disallow text that is longer than the value
+# specified by the -fixed option.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Entryfield::_checkLength {} {
+ if {$itk_option(-fixed) != 0} {
+ if [catch {::selection get -selection CLIPBOARD} pending] {
+ # Nothing in the clipboard. Check the primary selection.
+ if [catch {::selection get -selection PRIMARY} pending] {
+ # Nothing here either. Goodbye.
+ return
+ }
+ }
+ set len [expr {[string length $pending] + [string length [get]]}]
+ if {$len > $itk_option(-fixed)} {
+ uplevel #0 $itk_option(-invalid)
+ return -code break 0
+ }
+ }
+}
diff --git a/iwidgets/generic/extbutton.itk b/iwidgets/generic/extbutton.itk
new file mode 100644
index 00000000000..a898130a0d6
--- /dev/null
+++ b/iwidgets/generic/extbutton.itk
@@ -0,0 +1,439 @@
+#-------------------------------------------------------------------------------
+# Extbutton
+#-------------------------------------------------------------------------------
+# This [incr Widget] is pretty simple - it just extends the behavior of
+# the Tk button by allowing the user to add a bitmap or an image, which
+# can be placed at various locations relative to the text via the -imagepos
+# configuration option.
+#
+#-------------------------------------------------------------------------------
+# IMPORTANT NOTE: This [incr Widget] will only work with Tk 8.4 or later.
+#
+#-------------------------------------------------------------------------------
+# AUTHOR: Chad Smith E-mail: csmith@adc.com, itclguy@yahoo.com
+#-------------------------------------------------------------------------------
+# Permission to use, copy, modify, distribute, and license this software
+# and its documentation for any purpose is hereby granted as long as this
+# comment block remains intact.
+#-------------------------------------------------------------------------------
+
+#
+# Default resources
+#
+option add *Extbutton.borderwidth 2 widgetDefault
+option add *Extbutton.relief raised widgetDefault
+
+#
+# Usual options
+#
+itk::usual Extbutton {
+ keep -cursor -font
+}
+
+itcl::class iwidgets::Extbutton {
+ inherit itk::Widget
+
+ constructor {args} {}
+
+ itk_option define -activebackground activeBackground Foreground #ececec
+ itk_option define -bd borderwidth BorderWidth 2
+ itk_option define -bitmap bitmap Bitmap {}
+ itk_option define -command command Command {}
+ itk_option define -defaultring defaultring DefaultRing 0
+ itk_option define -defaultringpad defaultringpad Pad 4
+ itk_option define -image image Image {}
+ itk_option define -imagepos imagePos Position w
+ itk_option define -relief relief Relief raised
+ itk_option define -state state State normal
+ itk_option define -text text Text {}
+
+ public method invoke {} {eval $itk_option(-command)}
+ public method flash {}
+
+ private method changeColor {event_}
+ private method sink {}
+ private method raise {} {configure -relief $_oldValues(-relief)}
+
+ private variable _oldValues
+}
+
+
+#
+# Provide the usual lowercase access command.
+#
+proc iwidgets::extbutton {path_ args} {
+ uplevel iwidgets::Extbutton $path_ $args
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -bd
+#
+# DESCRIPTION: This isn't a new option. Similar to -image, we just need to
+# repack the frame when the borderwidth changes. This option is kept by
+# the private reliefframe component.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::bd {
+ pack $itk_component(frame) -padx 4 -pady 4
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -bitmap
+#
+# DESCRIPTION: This isn't a new option - we just need to reset the -image option
+# so that the user can toggle back and forth between images and bitmaps.
+# Otherwise, the image will take precedence and the user will be unable to
+# change to a bitmap without manually setting the label component's -image to
+# an empty string. This option is kept by the image component.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::bitmap {
+ if {$itk_option(-bitmap) == ""} {
+ return
+ }
+ if {$itk_option(-image) != ""} {
+ configure -image {}
+ }
+ pack $itk_component(frame) -padx 4 -pady 4
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -command
+#
+# DESCRIPTION: Invoke the given command to simulate the Tk button's -command
+# option. The command is invoked on <ButtonRelease-1> events only or by
+# direct calls to the public invoke() method.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::command {
+ if {$itk_option(-command) == ""} {
+ return
+ }
+
+ # Only create the tag binding if the button is operable.
+ if {$itk_option(-state) == "normal"} {
+ bind $this-commandtag <ButtonRelease-1> [itcl::code $this invoke]
+ }
+
+ # Associate the tag with each component if it's not already done.
+ if {[lsearch [bindtags $itk_interior] $this-commandtag] == -1} {
+ foreach component [component] {
+ bindtags [component $component] \
+ [linsert [bindtags [component $component]] end $this-commandtag]
+ }
+ }
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -defaultring
+#
+# DESCRIPTION: Controls display of the sunken frame surrounding the button.
+# This option simulates the pushbutton iwidget -defaultring option.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::defaultring {
+ switch -- $itk_option(-defaultring) {
+ 1 {set ring 1}
+ 0 {set ring 0}
+ default {
+ error "Invalid option for -defaultring: \"$itk_option(-defaultring)\". \
+ Should be 1 or 0."
+ }
+ }
+
+ if ($ring) {
+ $itk_component(ring) configure -borderwidth 2
+ pack $itk_component(reliefframe) -padx $itk_option(-defaultringpad) \
+ -pady $itk_option(-defaultringpad)
+ } else {
+ $itk_component(ring) configure -borderwidth 0
+ pack $itk_component(reliefframe) -padx 0 -pady 0
+ }
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -defaultringpad
+#
+# DESCRIPTION: The pad distance between the ring and the button.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::defaultringpad {
+ # Must be an integer.
+ if ![string is integer $itk_option(-defaultringpad)] {
+ error "Invalid value specified for -defaultringpad:\
+ \"$itk_option(-defaultringpad)\". Must be an integer."
+ }
+
+ # Let's go ahead and make the maximum padding 20 pixels. Surely no one
+ # will want more than that.
+ if {$itk_option(-defaultringpad) < 0 || $itk_option(-defaultringpad) > 20} {
+ error "Value for -defaultringpad must be between 0 and 20."
+ }
+
+ # If the ring is displayed, repack it according to the new padding amount.
+ if {$itk_option(-defaultring)} {
+ pack $itk_component(reliefframe) -padx $itk_option(-defaultringpad) \
+ -pady $itk_option(-defaultringpad)
+ }
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -image
+#
+# DESCRIPTION: This isn't a new option - we just need to repack the frame after
+# the image is changed in case the size is different than the previous one.
+# This option is kept by the image component.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::image {
+ pack $itk_component(frame) -padx 4 -pady 4
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -imagepos
+#
+# DESCRIPTION: Allows the user to move the image to different locations areound
+# the text. Valid options are n, nw, ne, s, sw, se e, en, es, w, wn or ws.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::imagepos {
+ switch -- $itk_option(-imagepos) {
+ n {set side top; set anchor center}
+ ne {set side top; set anchor e}
+ nw {set side top; set anchor w}
+
+ s {set side bottom; set anchor center}
+ se {set side bottom; set anchor e}
+ sw {set side bottom; set anchor w}
+
+ w {set side left; set anchor center}
+ wn {set side left; set anchor n}
+ ws {set side left; set anchor s}
+
+ e {set side right; set anchor center}
+ en {set side right; set anchor n}
+ es {set side right; set anchor s}
+
+ default {
+ error "Invalid option: \"$itk_option(-imagepos)\". \
+ Must be n, nw, ne, s, sw, se e, en, es, w, wn or ws."
+ }
+ }
+
+ pack $itk_component(image) -side $side -anchor $anchor
+ pack $itk_component(frame) -padx 4 -pady 4
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -relief
+#
+# DESCRIPTION: Move the frame component according to the relief to simulate
+# the text in a Tk button when its relief is changed.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::relief {
+ update idletasks
+ switch -- $itk_option(-relief) {
+ flat - ridge - groove {
+ place $itk_component(frame) -x 5 -y 5
+ }
+
+ raised {
+ place $itk_component(frame) -x 4 -y 4
+ }
+
+ sunken {
+ place $itk_component(frame) -x 6 -y 6
+ }
+
+ default {
+ error "Invalid option: \"$itk_option(-relief)\". \
+ Must be flat, ridge, groove, raised, or sunken."
+ }
+ }
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -state
+#
+# DESCRIPTION: Simulate the button's -state option.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::state {
+ switch -- $itk_option(-state) {
+ disabled {
+ bind $itk_interior <Enter> { }
+ bind $itk_interior <Leave> { }
+ bind $this-sunkentag <1> { }
+ bind $this-raisedtag <ButtonRelease-1> { }
+ bind $this-commandtag <ButtonRelease-1> { }
+ set _oldValues(-fg) [cget -foreground]
+ set _oldValues(-cursor) [cget -cursor]
+ configure -foreground $itk_option(-disabledforeground)
+ configure -cursor "X_cursor red black"
+ }
+
+ normal {
+ bind $itk_interior <Enter> [itcl::code $this changeColor enter]
+ bind $itk_interior <Leave> [itcl::code $this changeColor leave]
+ bind $this-sunkentag <1> [itcl::code $this sink]
+ bind $this-raisedtag <ButtonRelease-1> [itcl::code $this raise]
+ bind $this-commandtag <ButtonRelease-1> [itcl::code $this invoke]
+ configure -foreground $_oldValues(-fg)
+ configure -cursor $_oldValues(-cursor)
+ }
+
+ default {
+ error "Bad option for -state: \"$itk_option(-state)\". Should be\
+ normal or disabled."
+ }
+ }
+}
+
+
+#-------------------------------------------------------------------------------
+# OPTION: -text
+#
+# DESCRIPTION: This isn't a new option. Similar to -image, we just need to
+# repack the frame when the text changes.
+#-------------------------------------------------------------------------------
+itcl::configbody iwidgets::Extbutton::text {
+ pack $itk_component(frame) -padx 4 -pady 4
+}
+
+
+
+#-------------------------------------------------------------------------------
+# CONSTRUCTOR
+#-------------------------------------------------------------------------------
+itcl::body iwidgets::Extbutton::constructor {args} {
+ # Extbutton will not work with versions of Tk less than 8.4 (the
+ # -activeforeground option was added to the Tk label widget in 8.4, for
+ # example). So disallow its use unless the right wish is being used.
+ if {$::tk_version < 8.4} {
+ error "The extbutton \[incr Widget\] can only be used with versions of\
+ Tk greater than 8.3.\nYou're currently using version $::tk_version."
+ }
+
+ # This frame is optionally displayed as a "default ring" around the button.
+ itk_component add ring {
+ frame $itk_interior.ring -relief sunken
+ } {
+ rename -background -ringbackground ringBackground Background
+ }
+
+ # Add an outer frame for the widget's relief. Ideally we could just keep
+ # the hull's -relief, but it's too tricky to handle relief changes.
+ itk_component add -private reliefframe {
+ frame $itk_component(ring).f
+ } {
+ rename -borderwidth -bd borderwidth BorderWidth
+ keep -relief
+ usual
+ }
+
+ # This frame contains the image and text. It will be moved slightly to
+ # simulate the text in a Tk button when the button is depressed/raised.
+ itk_component add frame {
+ frame $itk_component(reliefframe).f -borderwidth 0
+ }
+
+ itk_component add image {
+ label $itk_component(frame).img -borderwidth 0
+ } {
+ keep -bitmap -background -image
+ rename -foreground -bitmapforeground foreground Foreground
+ }
+
+ itk_component add label {
+ label $itk_component(frame).txt -borderwidth 0
+ } {
+ keep -activeforeground -background -disabledforeground
+ keep -font -foreground -justify -text
+ }
+
+ pack $itk_component(image) $itk_component(label) -side left -padx 6 -pady 4
+ pack $itk_component(frame) -padx 4 -pady 4
+ pack $itk_component(reliefframe) -fill both
+ pack $itk_component(ring) -fill both
+
+ # Create a couple of binding tags for handling relief changes. Then
+ # add these tags to each component.
+ foreach component [component] {
+ bindtags [component $component] \
+ [linsert [bindtags [component $component]] end $this-sunkentag]
+ bindtags [component $component] \
+ [linsert [bindtags [component $component]] end $this-raisedtag]
+ }
+
+ set _oldValues(-fg) [cget -foreground]
+ set _oldValues(-cursor) [cget -cursor]
+
+ eval itk_initialize $args
+}
+
+
+#-------------------------------------------------------------------------------
+# METHOD: flash
+#
+# ACCESS: public
+#
+# DESCRIPTION: Simulate the Tk button flash command.
+#
+# ARGUMENTS: none
+#-------------------------------------------------------------------------------
+itcl::body iwidgets::Extbutton::flash {} {
+ set oldbg [cget -background]
+ config -background $itk_option(-activebackground)
+ update idletasks
+
+ after 50; config -background $oldbg; update idletasks
+ after 50; config -background $itk_option(-activebackground); update idletasks
+ after 50; config -background $oldbg
+}
+
+
+#-------------------------------------------------------------------------------
+# METHOD: changeColor
+#
+# ACCESS: private
+#
+# DESCRIPTION: This method is invoked by <Enter> and <Leave> events to change
+# the background and foreground colors of the widget.
+#
+# ARGUMENTS: event_ --> either "enter" or "leave"
+#-------------------------------------------------------------------------------
+itcl::body iwidgets::Extbutton::changeColor {event_} {
+ switch -- $event_ {
+ enter {
+ set _oldValues(-bg) [cget -background]
+ set _oldValues(-fg) [cget -foreground]
+ configure -background $itk_option(-activebackground)
+ configure -foreground $itk_option(-activeforeground)
+ }
+ leave {
+ configure -background $_oldValues(-bg)
+ configure -foreground $_oldValues(-fg)
+ }
+ }
+}
+
+
+#-------------------------------------------------------------------------------
+# METHOD: sink
+#
+# ACCESS: private
+#
+# DESCRIPTION: This method is invoked on <1> mouse events. It saves the
+# current relief for later restoral and configures the relief to sunken if
+# it isn't already sunken.
+#
+# ARGUMENTS: none
+#-------------------------------------------------------------------------------
+itcl::body iwidgets::Extbutton::sink {} {
+ set _oldValues(-relief) [cget -relief]
+ if {$_oldValues(-relief) == "sunken"} {
+ return
+ }
+ configure -relief sunken
+}
diff --git a/iwidgets/generic/extfileselectionbox.itk b/iwidgets/generic/extfileselectionbox.itk
new file mode 100644
index 00000000000..b3de7a7f4b3
--- /dev/null
+++ b/iwidgets/generic/extfileselectionbox.itk
@@ -0,0 +1,1187 @@
+#
+# Extfileselectionbox
+# ----------------------------------------------------------------------
+# Implements a file selection box that is a slightly extended version
+# of the OSF/Motif standard XmExtfileselectionbox composite widget.
+# The Extfileselectionbox differs from the Motif standard in that the
+# filter and selection fields are comboboxes and the files and directory
+# lists are in a paned window.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@spd.dsccc.com
+# Anthony L. Parent tony.parent@symbios.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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 Extfileselectionbox {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -insertbackground -insertborderwidth -insertofftime -insertontime \
+ -insertwidth -jump -labelfont -selectbackground -selectborderwidth \
+ -textbackground -textfont -troughcolor
+}
+
+# ------------------------------------------------------------------
+# EXTFILESELECTIONBOX
+# ------------------------------------------------------------------
+itcl::class iwidgets::Extfileselectionbox {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -childsitepos childSitePos Position s
+ itk_option define -fileson filesOn FilesOn true
+ itk_option define -dirson dirsOn DirsOn true
+ itk_option define -selectionon selectionOn SelectionOn true
+ itk_option define -filteron filterOn FilterOn true
+ itk_option define -mask mask Mask {*}
+ itk_option define -directory directory Directory {}
+ itk_option define -automount automount Automount {}
+ itk_option define -nomatchstring noMatchString NoMatchString {}
+ itk_option define -dirsearchcommand dirSearchCommand Command {}
+ itk_option define -filesearchcommand fileSearchCommand Command {}
+ itk_option define -selectioncommand selectionCommand Command {}
+ itk_option define -filtercommand filterCommand Command {}
+ itk_option define -selectdircommand selectDirCommand Command {}
+ itk_option define -selectfilecommand selectFileCommand Command {}
+ itk_option define -invalid invalid Command {bell}
+ itk_option define -filetype fileType FileType {regular}
+ itk_option define -width width Width 350
+ itk_option define -height height Height 300
+
+ public {
+ method childsite {}
+ method get {}
+ method filter {}
+ }
+
+ protected {
+ method _packComponents {{when later}}
+ method _updateLists {{when later}}
+ }
+
+ private {
+ method _selectDir {}
+ method _dblSelectDir {}
+ method _selectFile {}
+ method _selectSelection {}
+ method _selectFilter {}
+ method _setFilter {}
+ method _setSelection {}
+ method _setDirList {}
+ method _setFileList {}
+
+ method _nPos {}
+ method _sPos {}
+ method _ePos {}
+ method _wPos {}
+ method _topPos {}
+ method _bottomPos {}
+
+ variable _packToken "" ;# non-null => _packComponents pending
+ variable _updateToken "" ;# non-null => _updateLists pending
+ variable _pwd "." ;# present working dir
+ variable _interior ;# original interior setting
+ }
+}
+
+#
+# Provide a lowercased access method for the Extfileselectionbox class.
+#
+proc ::iwidgets::extfileselectionbox {pathName args} {
+ uplevel ::iwidgets::Extfileselectionbox $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Extfileselectionbox.borderWidth 2 widgetDefault
+
+option add *Extfileselectionbox.filterLabel Filter widgetDefault
+option add *Extfileselectionbox.dirsLabel Directories widgetDefault
+option add *Extfileselectionbox.filesLabel Files widgetDefault
+option add *Extfileselectionbox.selectionLabel Selection widgetDefault
+
+option add *Extfileselectionbox.width 350 widgetDefault
+option add *Extfileselectionbox.height 300 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::constructor {args} {
+ #
+ # Add back to the hull width and height options and make the
+ # borderwidth zero since we don't need it.
+ #
+ itk_option add hull.width hull.height
+ component hull configure -borderwidth 0
+
+ set _interior $itk_interior
+
+ #
+ # Create the filter entry.
+ #
+ itk_component add filter {
+ iwidgets::Combobox $itk_interior.filter -unique true \
+ -command [itcl::code $this _selectFilter] -exportselection 0 \
+ -labelpos nw -completion 0
+
+ } {
+ usual
+
+ rename -labeltext -filterlabel filterLabel Text
+ }
+
+ set cmd [$itk_component(filter) cget -command]
+ set cmd "$cmd;[itcl::code $this _selectFilter]"
+ $itk_component(filter) configure -command "$cmd" -selectioncommand "$cmd";
+
+ #
+ # Create a paned window for the directory and file lists.
+ #
+ itk_component add listpane {
+ iwidgets::Panedwindow $itk_interior.listpane -orient vertical
+ }
+
+ $itk_component(listpane) add dirs -margin 5
+ $itk_component(listpane) add files -margin 5
+
+ #
+ # Create the directory list.
+ #
+ itk_component add dirs {
+ iwidgets::Scrolledlistbox [$itk_component(listpane) childsite dirs].dirs \
+ -selectioncommand [itcl::code $this _selectDir] \
+ -selectmode single -exportselection 0 \
+ -visibleitems 1x1 -labelpos nw \
+ -hscrollmode static -vscrollmode static \
+ -dblclickcommand [itcl::code $this _dblSelectDir]
+ } {
+ usual
+
+ rename -labeltext -dirslabel dirsLabel Text
+ }
+ grid $itk_component(dirs) -sticky nsew
+ grid rowconfigure [$itk_component(listpane) childsite dirs] 0 -weight 1
+ grid columnconfigure [$itk_component(listpane) childsite dirs] 0 -weight 1
+
+ #
+ # Create the files list.
+ #
+ itk_component add files {
+ iwidgets::Scrolledlistbox [$itk_component(listpane) childsite files].files \
+ -selectioncommand [itcl::code $this _selectFile] \
+ -selectmode single -exportselection 0 \
+ -visibleitems 1x1 -labelpos nw \
+ -hscrollmode static -vscrollmode static
+ } {
+ usual
+
+ rename -labeltext -fileslabel filesLabel Text
+ }
+ grid $itk_component(files) -sticky nsew
+ grid rowconfigure [$itk_component(listpane) childsite files] 0 -weight 1
+ grid columnconfigure [$itk_component(listpane) childsite files] 0 -weight 1
+
+ #
+ # Create the selection entry.
+ #
+ itk_component add selection {
+ iwidgets::Combobox $itk_interior.selection -unique true \
+ -command [itcl::code $this _selectSelection] -exportselection 0 \
+ -labelpos nw -completion 0
+ } {
+ usual
+
+ rename -labeltext -selectionlabel selectionLabel Text
+ }
+
+ #
+ # Create the child site widget.
+ #
+ itk_component add -protected childsite {
+ frame $itk_interior.fsbchildsite
+ }
+
+ #
+ # Set the interior variable to the childsite for derived classes.
+ #
+ set itk_interior $itk_component(childsite)
+
+ #
+ # Explicitly handle configs that may have been ignored earlier.
+ #
+ eval itk_initialize $args
+
+ #
+ # When idle, pack the childsite and update the lists.
+ #
+ _packComponents
+ _updateLists
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::destructor {} {
+ if {$_packToken != ""} {after cancel $_packToken}
+ if {$_updateToken != ""} {after cancel $_updateToken}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -childsitepos
+#
+# Specifies the position of the child site in the selection box.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::childsitepos {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -fileson
+#
+# Specifies whether or not to display the files list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::fileson {
+ if {$itk_option(-fileson)} {
+ $itk_component(listpane) show files
+
+ _updateLists
+
+ } else {
+ $itk_component(listpane) hide files
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -dirson
+#
+# Specifies whether or not to display the dirs list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::dirson {
+ if {$itk_option(-dirson)} {
+ $itk_component(listpane) show dirs
+
+ _updateLists
+
+ } else {
+ $itk_component(listpane) hide dirs
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectionon
+#
+# Specifies whether or not to display the selection entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::selectionon {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -filteron
+#
+# Specifies whether or not to display the filter entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::filteron {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -mask
+#
+# Specifies the initial file mask string.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::mask {
+ global tcl_platform
+ set prefix $_pwd
+
+ #
+ # Remove automounter paths.
+ #
+ if {$tcl_platform(platform) == "unix"} {
+ if {$itk_option(-automount) != {}} {
+ foreach autoDir $itk_option(-automount) {
+ # Use catch because we can't be sure exactly what strings
+ # were passed into the -automount option
+ catch {
+ if {[regsub ^/$autoDir $prefix {} prefix] != 0} {
+ break
+ }
+ }
+ }
+ }
+ }
+
+ set curFilter $itk_option(-mask);
+ $itk_component(filter) delete entry 0 end
+ $itk_component(filter) insert entry 0 [file join "$_pwd" $itk_option(-mask)]
+
+ #
+ # Make sure the right most text is visable.
+ #
+ [$itk_component(filter) component entry] xview moveto 1
+}
+
+# ------------------------------------------------------------------
+# OPTION: -directory
+#
+# Specifies the initial default directory.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::directory {
+ if {$itk_option(-directory) != {}} {
+ if {! [file exists $itk_option(-directory)]} {
+ error "bad directory option \"$itk_option(-directory)\":\
+ directory does not exist"
+ }
+
+ set olddir [pwd]
+ cd $itk_option(-directory)
+ set _pwd [pwd]
+ cd $olddir
+
+ configure -mask $itk_option(-mask)
+ _selectFilter
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -automount
+#
+# Specifies list of directory prefixes to ignore. Typically, this
+# option would be used with values such as:
+# -automount {export tmp_mnt}
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::automount {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -nomatchstring
+#
+# Specifies the string to be displayed in the files list should
+# not regular files exist in the directory.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::nomatchstring {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -dirsearchcommand
+#
+# Specifies a command to be executed to perform a directory search.
+# The command will receive the current working directory and filter
+# mask as arguments. The command should return a list of files which
+# will be placed into the directory list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::dirsearchcommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -filesearchcommand
+#
+# Specifies a command to be executed to perform a file search.
+# The command will receive the current working directory and filter
+# mask as arguments. The command should return a list of files which
+# will be placed into the file list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::filesearchcommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectioncommand
+#
+# Specifies a command to be executed upon pressing return in the
+# selection entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::selectioncommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -filtercommand
+#
+# Specifies a command to be executed upon pressing return in the
+# filter entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::filtercommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectdircommand
+#
+# Specifies a command to be executed following selection of a
+# directory in the directory list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::selectdircommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectfilecommand
+#
+# Specifies a command to be executed following selection of a
+# file in the files list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::selectfilecommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -invalid
+#
+# Specify a command to executed should the filter contents be
+# proven invalid.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::invalid {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -filetype
+#
+# Specify the type of files which may appear in the file list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::filetype {
+ switch $itk_option(-filetype) {
+ regular -
+ directory -
+ any {
+ }
+ default {
+ error "bad filetype option \"$itk_option(-filetype)\":\
+ should be regular, directory, or any"
+ }
+ }
+
+ _updateLists
+}
+
+# ------------------------------------------------------------------
+# OPTION: -width
+#
+# Specifies the width of the file selection box. The value may be
+# specified in any of the forms acceptable to Tk_GetPixels.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::width {
+ #
+ # The width option was added to the hull in the constructor.
+ # So, any width value given is passed automatically to the
+ # hull. All we have to do is play with the propagation.
+ #
+ if {$itk_option(-width) != 0} {
+ set propagate 0
+ } else {
+ set propagate 1
+ }
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $itk_component(hull)] != $propagate} {
+ grid propagate $itk_component(hull) $propagate
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -height
+#
+# Specifies the height of the file selection box. The value may be
+# specified in any of the forms acceptable to Tk_GetPixels.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Extfileselectionbox::height {
+ #
+ # The height option was added to the hull in the constructor.
+ # So, any height value given is passed automatically to the
+ # hull. All we have to do is play with the propagation.
+ #
+ if {$itk_option(-height) != 0} {
+ set propagate 0
+ } else {
+ set propagate 1
+ }
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $itk_component(hull)] != $propagate} {
+ grid propagate $itk_component(hull) $propagate
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Returns the path name of the child site widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::childsite {} {
+ return $itk_component(childsite)
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Returns the current selection.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::get {} {
+ return [$itk_component(selection) get]
+}
+
+# ------------------------------------------------------------------
+# METHOD: filter
+#
+# The user has pressed Return in the filter. Make sure the contents
+# contain a valid directory before setting default to directory.
+# Use the invalid option to warn the user of any problems.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::filter {} {
+ set newdir [file dirname [$itk_component(filter) get]]
+
+ if {! [file exists $newdir]} {
+ uplevel #0 "$itk_option(-invalid)"
+ return
+ }
+
+ set _pwd $newdir;
+ if {$_pwd == "."} {set _pwd [pwd]};
+
+ _updateLists
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _updateLists ?now?
+#
+# Updates the contents of both the file and directory lists, as well
+# resets the positions of the filter, and lists.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_updateLists {{when "later"}} {
+ switch -- $when {
+ later {
+ if {$_updateToken == ""} {
+ set _updateToken [after idle [itcl::code $this _updateLists now]]
+ }
+ }
+ now {
+ if {$itk_option(-dirson)} {_setDirList}
+ if {$itk_option(-fileson)} {_setFileList}
+
+ if {$itk_option(-filteron)} {
+ _setFilter
+ }
+ if {$itk_option(-selectionon)} {
+ $itk_component(selection) icursor end
+ }
+ if {$itk_option(-dirson)} {
+ $itk_component(dirs) justify left
+ }
+ if {$itk_option(-fileson)} {
+ $itk_component(files) justify left
+ }
+ set _updateToken ""
+ }
+ default {
+ error "bad option \"$when\": should be later or now"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setFilter
+#
+# Set the filter to the current selection in the directory list plus
+# any existing mask in the filter. Translate the two special cases
+# of '.', and '..' directory names to full path names..
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_setFilter {} {
+ global tcl_platform
+ set prefix [$itk_component(dirs) getcurselection]
+ set curFilter [file tail [$itk_component(filter) get]]
+
+ while {[regexp {\.$} $prefix]} {
+ if {[file tail $prefix] == "."} {
+ if {$prefix == "."} {
+ if {$_pwd == "."} {
+ set _pwd [pwd]
+ } elseif {$_pwd == ".."} {
+ set _pwd [file dirname [pwd]]
+ }
+ set prefix $_pwd
+ } else {
+ set prefix [file dirname $prefix]
+ }
+ } elseif {[file tail $prefix] == ".."} {
+ if {$prefix != ".."} {
+ set prefix [file dirname [file dirname $prefix]]
+ } else {
+ if {$_pwd == "."} {
+ set _pwd [pwd]
+ } elseif {$_pwd == ".."} {
+ set _pwd [file dirname [pwd]]
+ }
+ set prefix [file dirname "$_pwd"]
+ }
+ } else {
+ break
+ }
+ }
+
+ if { [file pathtype $prefix] != "absolute" } {
+ set prefix [file join "$_pwd" $prefix]
+ }
+
+ #
+ # Remove automounter paths.
+ #
+ if {$tcl_platform(platform) == "unix"} {
+ if {$itk_option(-automount) != {}} {
+ foreach autoDir $itk_option(-automount) {
+ # Use catch because we can't be sure exactly what strings
+ # were passed into the -automount option
+ catch {
+ if {[regsub ^/$autoDir $prefix {} prefix] != 0} {
+ break
+ }
+ }
+ }
+ }
+ }
+
+ $itk_component(filter) delete entry 0 end
+ $itk_component(filter) insert entry 0 [file join $prefix $curFilter]
+
+ if {[info level -1] != "_selectDir"} {
+ $itk_component(filter) insert list 0 [file join $prefix $curFilter]
+ }
+
+ #
+ # Make sure insertion cursor is at the end.
+ #
+ $itk_component(filter) icursor end
+
+ #
+ # Make sure the right most text is visable.
+ #
+ [$itk_component(filter) component entry] xview moveto 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setSelection
+#
+# Set the contents of the selection entry to either the current
+# selection of the file or directory list dependent on which lists
+# are currently mapped. For the file list, avoid seleciton of the
+# no match string. As for the directory list, translate file names.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_setSelection {} {
+ global tcl_platform
+ $itk_component(selection) delete entry 0 end
+
+ if {$itk_option(-fileson)} {
+ set selection [$itk_component(files) getcurselection]
+
+ if {$selection != $itk_option(-nomatchstring)} {
+ if {[file pathtype $selection] != "absolute"} {
+ set selection [file join "$_pwd" $selection]
+ }
+
+ #
+ # Remove automounter paths.
+ #
+ if {$tcl_platform(platform) == "unix"} {
+ if {$itk_option(-automount) != {}} {
+ foreach autoDir $itk_option(-automount) {
+ # Use catch because we can't be sure exactly what strings
+ # were passed into the -automount option
+ catch {
+ if {[regsub ^/$autoDir $selection {} selection] != 0} {
+ break
+ }
+ }
+ }
+ }
+ }
+
+ $itk_component(selection) insert entry 0 $selection
+ } else {
+ $itk_component(files) selection clear 0 end
+ }
+
+ } else {
+ set selection [$itk_component(dirs) getcurselection]
+
+ if {[file tail $selection] == "."} {
+ if {$selection != "."} {
+ set selection [file dirname $selection]
+ } else {
+ set selection "$_pwd"
+ }
+ } elseif {[file tail $selection] == ".."} {
+ if {$selection != ".."} {
+ set selection [file dirname [file dirname $selection]]
+ } else {
+ set selection [file join "$_pwd" ..]
+ }
+ } else {
+ set selection [file join "$_pwd" $selection]
+ }
+
+ #
+ # Remove automounter paths.
+ #
+ if {$tcl_platform(platform) == "unix"} {
+ if {$itk_option(-automount) != {}} {
+ foreach autoDir $itk_option(-automount) {
+ # Use catch because we can't be sure exactly what strings
+ # were passed into the -automount option
+ catch {
+ if {[regsub ^/$autoDir $selection {} selection] != 0} {
+ break
+ }
+ }
+ }
+ }
+ }
+
+ $itk_component(selection) insert entry 0 $selection
+ }
+
+ $itk_component(selection) insert list 0 $selection
+ $itk_component(selection) icursor end
+
+ #
+ # Make sure the right most text is visable.
+ #
+ [$itk_component(selection) component entry] xview moveto 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setDirList
+#
+# Clear the directory list and dependent on whether the user has
+# defined their own search procedure or not fill the list with their
+# results or those of a glob. Select the first element if it exists.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_setDirList {} {
+ $itk_component(dirs) clear
+
+ if {$itk_option(-dirsearchcommand) == {}} {
+ set cwd "$_pwd"
+
+ set counter 0
+ set currentIndex ""
+ foreach i [lsort [glob -nocomplain \
+ [file join $cwd .*] [file join $cwd *]]] {
+ if {[file isdirectory $i]} {
+ set insert "[file tail $i]"
+ if {$insert == "."} {
+ set currentIndex $counter
+ }
+ $itk_component(dirs) insert end "$insert"
+ incr counter
+ }
+ }
+
+ } else {
+ set mask [file tail [$itk_component(filter) get]]
+
+ foreach file [uplevel #0 $itk_option(-dirsearchcommand) "$_pwd" $mask] {
+ $itk_component(dirs) insert end $file
+ }
+ }
+
+ if {[$itk_component(dirs) size]} {
+ $itk_component(dirs) selection clear 0 end
+ if {$currentIndex != ""} {
+ $itk_component(dirs) selection set $currentIndex
+ } else {
+ $itk_component(dirs) selection set 0
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setFileList
+#
+# Clear the file list and dependent on whether the user has defined
+# their own search procedure or not fill the list with their results
+# or those of a 'glob'. If the files list has no contents, then set
+# the files list to the 'nomatchstring'. Clear all selections.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_setFileList {} {
+ $itk_component(files) clear
+ set mask [file tail [$itk_component(filter) get]]
+
+ if {$itk_option(-filesearchcommand) == {}} {
+ if {$mask == "*"} {
+ set files [lsort [glob -nocomplain \
+ [file join "$_pwd" .*] [file join "$_pwd" *]]]
+ } else {
+ set files [lsort [glob -nocomplain [file join "$_pwd" $mask]]]
+ }
+
+ foreach i $files {
+ if {($itk_option(-filetype) == "regular" && \
+ ! [file isdirectory $i]) || \
+ ($itk_option(-filetype) == "directory" && \
+ [file isdirectory $i]) || \
+ ($itk_option(-filetype) == "any")} {
+ set insert "[file tail $i]"
+ $itk_component(files) insert end "$insert"
+ }
+ }
+
+ } else {
+ foreach file [uplevel #0 $itk_option(-filesearchcommand) "$_pwd" $mask] {
+ $itk_component(files) insert end $file
+ }
+ }
+
+ if {[$itk_component(files) size] == 0} {
+ if {$itk_option(-nomatchstring) != {}} {
+ $itk_component(files) insert end $itk_option(-nomatchstring)
+ }
+ }
+
+ $itk_component(files) selection clear 0 end
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _selectDir
+#
+# For a selection in the directory list, set the filter and possibly
+# the selection entry based on the fileson option.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_selectDir {} {
+ _setFilter
+
+ if {$itk_option(-fileson)} {} {
+ _setSelection
+ }
+
+ if {$itk_option(-selectdircommand) != {}} {
+ uplevel #0 $itk_option(-selectdircommand)
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _dblSelectDir
+#
+# For a double click event in the directory list, select the
+# directory, set the default to the selection, and update both the
+# file and directory lists.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_dblSelectDir {} {
+ filter
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _selectFile
+#
+# The user has selected a file. Put the current selection in the
+# file list in the selection entry widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_selectFile {} {
+ _setSelection
+
+ if {$itk_option(-selectfilecommand) != {}} {
+ uplevel #0 $itk_option(-selectfilecommand)
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _selectSelection
+#
+# The user has pressed Return in the selection entry widget. Call
+# the defined selection command if it exists.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_selectSelection {} {
+ if {$itk_option(-selectioncommand) != {}} {
+ uplevel #0 $itk_option(-selectioncommand)
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _selectFilter
+#
+# The user has pressed Return in the filter entry widget. Call the
+# defined selection command if it exists, otherwise just filter.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_selectFilter {} {
+ if {$itk_option(-filtercommand) != {}} {
+ uplevel #0 $itk_option(-filtercommand)
+ } else {
+ filter
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _packComponents
+#
+# Pack the selection, items, and child site widgets based on options.
+# Using the -in option of pack, put the childsite around the frame
+# in the hull for n, s, e, and w positions. Make sure and raise
+# the child site since using the 'in' option may obscure the site.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_packComponents {{when "later"}} {
+ if {$when == "later"} {
+ if {$_packToken == ""} {
+ set _packToken [after idle [itcl::code $this _packComponents now]]
+ }
+ return
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ set _packToken ""
+
+ #
+ # Forget about any previous placements via the grid and
+ # reset all the possible minsizes and weights for all
+ # the rows and columns.
+ #
+ foreach component {childsite listpane filter selection} {
+ grid forget $itk_component($component)
+ }
+
+ for {set row 0} {$row < 6} {incr row} {
+ grid rowconfigure $_interior $row -minsize 0 -weight 0
+ }
+
+ for {set col 0} {$col < 3} {incr col} {
+ grid columnconfigure $_interior $col -minsize 0 -weight 0
+ }
+
+ #
+ # Place all the components based on the childsite poisition
+ # option.
+ #
+ switch $itk_option(-childsitepos) {
+ n { _nPos }
+
+ w { _wPos }
+
+ s { _sPos }
+
+ e { _ePos }
+
+ top { _topPos }
+
+ bottom { _bottomPos }
+
+ default {
+ error "bad childsitepos option \"$itk_option(-childsitepos)\":\
+ should be n, e, s, w, top, or bottom"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _nPos
+#
+# Position the childsite to the north and all the other components
+# appropriately based on the individual "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_nPos {} {
+ grid $itk_component(childsite) -row 0 -column 0 \
+ -columnspan 1 -rowspan 1 -sticky nsew -padx 5
+
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 1 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ grid rowconfigure $_interior 2 -minsize 7
+ }
+
+ grid $itk_component(listpane) -row 3 -column 0 \
+ -columnspan 1 -sticky nsew
+
+ grid rowconfigure $_interior 3 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 4 -minsize 7
+ grid $itk_component(selection) -row 5 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ }
+
+ grid columnconfigure $_interior 0 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _sPos
+#
+# Position the childsite to the south and all the other components
+# appropriately based on the individual "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_sPos {} {
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ grid rowconfigure $_interior 1 -minsize 7
+ }
+
+ grid $itk_component(listpane) -row 2 -column 0 \
+ -columnspan 1 -sticky nsew
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 3 -minsize 7
+ grid $itk_component(selection) -row 4 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ }
+
+ grid $itk_component(childsite) -row 5 -column 0 \
+ -columnspan 1 -rowspan 1 -sticky nsew -padx 5
+
+ grid columnconfigure $_interior 0 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _ePos
+#
+# Position the childsite to the east and all the other components
+# appropriately based on the individual "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_ePos {} {
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ grid rowconfigure $_interior 1 -minsize 7
+ }
+
+ grid $itk_component(listpane) -row 2 -column 0 \
+ -columnspan 1 -sticky nsew
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 3 -minsize 7
+ grid $itk_component(selection) -row 4 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ }
+
+ grid $itk_component(childsite) -row 0 -column 1 \
+ -rowspan 5 -columnspan 1 -sticky nsew
+
+ grid columnconfigure $_interior 0 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _wPos
+#
+# Position the childsite to the west and all the other components
+# appropriately based on the individual "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_wPos {} {
+ grid $itk_component(childsite) -row 0 -column 0 \
+ -rowspan 5 -columnspan 1 -sticky nsew
+
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 1 \
+ -columnspan 1 -sticky ew -padx 5
+ grid rowconfigure $_interior 1 -minsize 7
+ }
+
+ grid $itk_component(listpane) -row 2 -column 1 \
+ -columnspan 1 -sticky nsew
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 3 -minsize 7
+ grid $itk_component(selection) -row 4 -column 1 \
+ -columnspan 1 -sticky ew -padx 5
+ }
+
+ grid columnconfigure $_interior 1 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _topPos
+#
+# Position the childsite below the filter but above the lists and
+# all the other components appropriately based on the individual
+# "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_topPos {} {
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ }
+
+ grid $itk_component(childsite) -row 1 -column 0 \
+ -columnspan 1 -rowspan 1 -sticky nsew -padx 5
+
+ grid $itk_component(listpane) -row 2 -column 0 -sticky nsew
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 3 -minsize 7
+ grid $itk_component(selection) -row 4 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ }
+
+ grid columnconfigure $_interior 0 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _bottomPos
+#
+# Position the childsite below the lists and above the selection
+# and all the other components appropriately based on the individual
+# "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectionbox::_bottomPos {} {
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ grid rowconfigure $_interior 1 -minsize 7
+ }
+
+ grid $itk_component(listpane) -row 2 -column 0 -sticky nsew
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ grid $itk_component(childsite) -row 3 -column 0 \
+ -columnspan 1 -rowspan 1 -sticky nsew -padx 5
+
+ if {$itk_option(-selectionon)} {
+ grid $itk_component(selection) -row 4 -column 0 \
+ -columnspan 1 -sticky ew -padx 5
+ }
+
+ grid columnconfigure $_interior 0 -weight 1
+}
diff --git a/iwidgets/generic/extfileselectiondialog.itk b/iwidgets/generic/extfileselectiondialog.itk
new file mode 100644
index 00000000000..220a8fcb33a
--- /dev/null
+++ b/iwidgets/generic/extfileselectiondialog.itk
@@ -0,0 +1,182 @@
+#
+# Extfileselectiondialog
+# ----------------------------------------------------------------------
+# Implements a file selection dialog that is a slightly extended version
+# of the OSF/Motif standard composite widget. The Extfileselectionbox
+# differs from the Motif standard in that the filter and selection
+# fields are comboboxes and the files and directory lists are in a
+# paned window.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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 Extfileselectiondialog {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -insertbackground -insertborderwidth -insertofftime -insertontime \
+ -insertwidth -jump -labelfont -modality -selectbackground \
+ -selectborderwidth -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# EXTFILESELECTIONDIALOG
+# ------------------------------------------------------------------
+itcl::class iwidgets::Extfileselectiondialog {
+ inherit iwidgets::Dialog
+
+ constructor {args} {}
+
+ public {
+ method childsite {}
+ method get {}
+ method filter {}
+ }
+
+ protected method _dbldir {}
+}
+
+#
+# Provide a lowercased access method for the Extfileselectiondialog class.
+#
+proc ::iwidgets::extfileselectiondialog {pathName args} {
+ uplevel ::iwidgets::Extfileselectiondialog $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Extfileselectiondialog.borderWidth 2 widgetDefault
+
+option add *Extfileselectiondialog.title "File Selection Dialog" widgetDefault
+
+option add *Extfileselectiondialog.width 350 widgetDefault
+option add *Extfileselectiondialog.height 400 widgetDefault
+
+option add *Extfileselectiondialog.master "." widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectiondialog::constructor {args} {
+ component hull configure -borderwidth 0
+ itk_option add hull.width hull.height
+
+ #
+ # Turn off pack propagation for the hull widget so the width
+ # and height options become active.
+ #
+ pack propagate $itk_component(hull) no
+
+ #
+ # Instantiate a file selection box widget.
+ #
+ itk_component add fsb {
+ iwidgets::Extfileselectionbox $itk_interior.fsb -width 150 -height 150 \
+ -selectioncommand [itcl::code $this invoke] \
+ -selectdircommand [itcl::code $this default Apply] \
+ -selectfilecommand [itcl::code $this default OK]
+ } {
+ usual
+
+ keep -labelfont -childsitepos -directory -dirslabel \
+ -dirsearchcommand -dirson -fileslabel -fileson \
+ -filesearchcommand -filterlabel -filteron \
+ -filetype -invalid -mask -nomatchstring \
+ -selectionlabel -selectionon -sashcursor
+ }
+ grid $itk_component(fsb) -sticky nsew
+ grid rowconfigure $itk_interior 0 -weight 1
+ grid columnconfigure $itk_interior 0 -weight 1
+
+ $itk_component(fsb) component filter configure \
+ -focuscommand [itcl::code $this default Apply]
+ $itk_component(fsb) component selection configure \
+ -focuscommand [itcl::code $this default OK]
+ $itk_component(fsb) component dirs configure \
+ -dblclickcommand [itcl::code $this _dbldir]
+ $itk_component(fsb) component files configure \
+ -dblclickcommand [itcl::code $this invoke]
+
+ buttonconfigure Apply -text "Filter" \
+ -command [itcl::code $itk_component(fsb) filter]
+
+ set itk_interior [$itk_component(fsb) childsite]
+
+ hide Help
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Thinwrapped method of file selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectiondialog::childsite {} {
+ return [$itk_component(fsb) childsite]
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Thinwrapped method of file selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectiondialog::get {} {
+ return [$itk_component(fsb) get]
+}
+
+# ------------------------------------------------------------------
+# METHOD: filter
+#
+# Thinwrapped method of file selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectiondialog::filter {} {
+ return [$itk_component(fsb) filter]
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _dbldir
+#
+# Double select in directory list. If the files list is on then
+# make the default button the filter and invoke. If not, just invoke.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Extfileselectiondialog::_dbldir {} {
+ if {$itk_option(-fileson)} {
+ default Apply
+ }
+
+ invoke
+}
+
diff --git a/iwidgets/generic/feedback.itk b/iwidgets/generic/feedback.itk
new file mode 100644
index 00000000000..5fe5a84d224
--- /dev/null
+++ b/iwidgets/generic/feedback.itk
@@ -0,0 +1,212 @@
+#
+# Feedback
+# ----------------------------------------------------------------------
+# Implements a Feedback widget, to display feedback on the status of an
+# process to the user. Display is given as a percentage and as a
+# thermometer type bar. Options exist for adding a label and controlling its
+# position.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Kris Raney EMAIL: kraney@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1996 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.
+# ======================================================================
+
+# Acknowledgements:
+#
+# Special thanks go to Sam Shen(SLShen@lbl.gov), as this code is based on his
+# feedback.tcl code from tk inspect. The original code is copyright 1995
+# Lawrence Berkeley Laboratory.
+#
+# This software is copyright (C) 1994 by the Lawrence Berkeley Laboratory.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that: (1) source code distributions
+# retain the above copyright notice and this paragraph in its entirety, (2)
+# distributions including binary code include the above copyright notice and
+# this paragraph in its entirety in the documentation or other materials
+# provided with the distribution, and (3) all advertising materials mentioning
+# features or use of this software display the following acknowledgement:
+# ``This product includes software developed by the University of California,
+# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+# the University nor the names of its contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+#
+# Default resources.
+#
+option add *Feedback.borderWidth 2 widgetDefault
+option add *Feedback.labelPos n widgetDefault
+option add *Feedback.barHeight 20 widgetDefault
+option add *Feedback.troughColor White widgetDefault
+option add *Feedback.barColor Blue widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Feedback {
+ keep -background -cursor -foreground
+}
+
+# ------------------------------------------------------------------
+# FEEDBACK
+# ------------------------------------------------------------------
+itcl::class iwidgets::Feedback {
+ inherit iwidgets::Labeledwidget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -steps steps Steps 10
+
+ public {
+ method reset {}
+ method step {{inc 1}}
+ }
+
+ private {
+ method _display
+
+ variable _barwidth 0
+ variable _stepval 0
+ }
+}
+
+#
+# Provide a lowercased access method for the Dialogshell class.
+#
+proc ::iwidgets::feedback {pathName args} {
+ uplevel ::iwidgets::Feedback $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Feedback::constructor {args} {
+ itk_component add trough {
+ frame $itk_interior.trough -relief sunken
+ } {
+ usual
+ keep -borderwidth
+ rename -background -troughcolor troughColor TroughColor
+ rename -height -barheight barHeight Height
+ }
+
+ itk_component add bar {
+ frame $itk_component(trough).bar -relief raised
+ } {
+ usual
+ keep -borderwidth
+ rename -background -barcolor barColor BarColor
+ rename -height -barheight barHeight Height
+ }
+ pack $itk_component(bar) -side left -fill y -anchor w
+
+ itk_component add percentage {
+ label $itk_interior.percentage -text "0%"
+ }
+ grid $itk_component(trough) -row 1 -column 0 -sticky sew -padx 2 -pady 2
+ grid $itk_component(percentage) -row 2 -column 0 -sticky nsew -padx 2 -pady 2
+ grid rowconfigure $itk_interior 0 -weight 1
+ grid rowconfigure $itk_interior 1 -weight 1
+ grid columnconfigure $itk_interior 0 -weight 1
+
+ bind $itk_component(hull) <Configure> [itcl::code $this _display]
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Feedback::destructor {} {
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -steps
+#
+# Set the total number of steps.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Feedback::steps {
+ step 0
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: _display
+#
+# Displays the bar in the trough with the width set using the current number
+# of steps.
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Feedback::_display {} {
+ update idletasks
+ set troughwidth [winfo width $itk_component(trough)]
+ set _barwidth [expr {
+ (1.0*$troughwidth-(2.0*[$itk_component(trough) cget -borderwidth])) /
+ $itk_option(-steps)}]
+ set fraction [expr {int((1.0*$_stepval)/$itk_option(-steps)*100.0)}]
+
+ $itk_component(percentage) config -text "$fraction%"
+ $itk_component(bar) config -width [expr {$_barwidth*$_stepval}]
+
+ update
+}
+
+# ------------------------------------------------------------------
+# METHOD: reset
+#
+# Resets the status bar to 0
+# ------------------------------------------------------------------
+itcl::body iwidgets::Feedback::reset {} {
+ set _stepval 0
+ _display
+}
+
+# ------------------------------------------------------------------
+# METHOD: step ?inc?
+#
+# Increase the value of the status bar by inc. Default to 1
+# ------------------------------------------------------------------
+itcl::body iwidgets::Feedback::step {{inc 1}} {
+
+ if {$_stepval >= $itk_option(-steps)} {
+ return
+ }
+
+ incr _stepval $inc
+ _display
+}
diff --git a/iwidgets/generic/fileselectionbox.itk b/iwidgets/generic/fileselectionbox.itk
new file mode 100644
index 00000000000..b083c5020b7
--- /dev/null
+++ b/iwidgets/generic/fileselectionbox.itk
@@ -0,0 +1,1296 @@
+#
+# Fileselectionbox
+# ----------------------------------------------------------------------
+# Implements a file selection box in a style similar to the OSF/Motif
+# standard XmFileselectionbox composite widget. The Fileselectionbox
+# is composed of directory and file scrolled lists as well as filter
+# and selection entry fields.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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 Fileselectionbox {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -insertbackground -insertborderwidth -insertofftime -insertontime \
+ -insertwidth -jump -labelfont -selectbackground -selectborderwidth \
+ -textbackground -textfont -troughcolor
+}
+
+# ------------------------------------------------------------------
+# FILESELECTIONBOX
+# ------------------------------------------------------------------
+itcl::class iwidgets::Fileselectionbox {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -childsitepos childSitePos Position s
+ itk_option define -fileson filesOn FilesOn true
+ itk_option define -dirson dirsOn DirsOn true
+ itk_option define -selectionon selectionOn SelectionOn true
+ itk_option define -filteron filterOn FilterOn true
+ itk_option define -mask mask Mask {*}
+ itk_option define -directory directory Directory {}
+ itk_option define -automount automount Automount {}
+ itk_option define -nomatchstring noMatchString NoMatchString {}
+ itk_option define -dirsearchcommand dirSearchCommand Command {}
+ itk_option define -filesearchcommand fileSearchCommand Command {}
+ itk_option define -selectioncommand selectionCommand Command {}
+ itk_option define -filtercommand filterCommand Command {}
+ itk_option define -selectdircommand selectDirCommand Command {}
+ itk_option define -selectfilecommand selectFileCommand Command {}
+ itk_option define -invalid invalid Command {bell}
+ itk_option define -filetype fileType FileType {regular}
+ itk_option define -width width Width 350
+ itk_option define -height height Height 300
+
+ public {
+ method childsite {}
+ method get {}
+ method filter {}
+ }
+
+ public {
+ method _selectDir {}
+ method _dblSelectDir {}
+ method _selectFile {}
+ method _selectSelection {}
+ method _selectFilter {}
+ }
+
+ protected {
+ method _packComponents {{when later}}
+ method _updateLists {{when later}}
+ }
+
+ private {
+ method _setFilter {}
+ method _setSelection {}
+ method _setDirList {}
+ method _setFileList {}
+
+ method _nPos {}
+ method _sPos {}
+ method _ePos {}
+ method _wPos {}
+ method _topPos {}
+ method _centerPos {}
+ method _bottomPos {}
+
+ variable _packToken "" ;# non-null => _packComponents pending
+ variable _updateToken "" ;# non-null => _updateLists pending
+ variable _pwd "." ;# present working dir
+ variable _interior ;# original interior setting
+ }
+}
+
+#
+# Provide a lowercased access method for the Fileselectionbox class.
+#
+proc ::iwidgets::fileselectionbox {pathName args} {
+ uplevel ::iwidgets::Fileselectionbox $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Fileselectionbox.borderWidth 2 widgetDefault
+
+option add *Fileselectionbox.filterLabel Filter widgetDefault
+option add *Fileselectionbox.dirsLabel Directories widgetDefault
+option add *Fileselectionbox.filesLabel Files widgetDefault
+option add *Fileselectionbox.selectionLabel Selection widgetDefault
+
+option add *Fileselectionbox.width 350 widgetDefault
+option add *Fileselectionbox.height 300 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::constructor {args} {
+ #
+ # Add back to the hull width and height options and make the
+ # borderwidth zero since we don't need it.
+ #
+ itk_option add hull.width hull.height
+ component hull configure -borderwidth 0
+
+ set _interior $itk_interior
+
+ #
+ # Create the filter entry.
+ #
+ itk_component add filter {
+ iwidgets::Entryfield $itk_interior.filter -labelpos nw \
+ -command [itcl::code $this _selectFilter] -exportselection 0
+ } {
+ usual
+
+ rename -labeltext -filterlabel filterLabel Text
+ }
+
+ #
+ # Create the directory list.
+ #
+ itk_component add dirs {
+ iwidgets::Scrolledlistbox $itk_interior.dirs \
+ -selectioncommand [itcl::code $this _selectDir] \
+ -selectmode single -exportselection 0 \
+ -visibleitems 1x1 -labelpos nw \
+ -hscrollmode static -vscrollmode static \
+ -dblclickcommand [itcl::code $this _dblSelectDir]
+ } {
+ usual
+
+ rename -labeltext -dirslabel dirsLabel Text
+ }
+
+ #
+ # Create the files list.
+ #
+ itk_component add files {
+ iwidgets::Scrolledlistbox $itk_interior.files \
+ -selectioncommand [itcl::code $this _selectFile] \
+ -selectmode single -exportselection 0 \
+ -visibleitems 1x1 -labelpos nw \
+ -hscrollmode static -vscrollmode static
+ } {
+ usual
+
+ rename -labeltext -fileslabel filesLabel Text
+ }
+
+ #
+ # Create the selection entry.
+ #
+ itk_component add selection {
+ iwidgets::Entryfield $itk_interior.selection -labelpos nw \
+ -command [itcl::code $this _selectSelection] -exportselection 0
+ } {
+ usual
+
+ rename -labeltext -selectionlabel selectionLabel Text
+ }
+
+ #
+ # Create the child site widget.
+ #
+ itk_component add -protected childsite {
+ frame $itk_interior.fsbchildsite
+ }
+
+ #
+ # Set the interior variable to the childsite for derived classes.
+ #
+ set itk_interior $itk_component(childsite)
+
+ #
+ # Explicitly handle configs that may have been ignored earlier.
+ #
+ eval itk_initialize $args
+
+ #
+ # When idle, pack the childsite and update the lists.
+ #
+ _packComponents
+ _updateLists
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::destructor {} {
+ if {$_packToken != ""} {after cancel $_packToken}
+ if {$_updateToken != ""} {after cancel $_updateToken}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -childsitepos
+#
+# Specifies the position of the child site in the selection box.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::childsitepos {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -fileson
+#
+# Specifies whether or not to display the files list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::fileson {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -dirson
+#
+# Specifies whether or not to display the dirs list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::dirson {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectionon
+#
+# Specifies whether or not to display the selection entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::selectionon {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -filteron
+#
+# Specifies whether or not to display the filter entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::filteron {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -mask
+#
+# Specifies the initial file mask string.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::mask {
+ global tcl_platform
+ set prefix $_pwd
+
+ #
+ # Remove automounter paths.
+ #
+ if {$tcl_platform(platform) == "unix"} {
+ if {$itk_option(-automount) != {}} {
+ foreach autoDir $itk_option(-automount) {
+ # Use catch because we can't be sure exactly what strings
+ # were passed into the -automount option
+ catch {
+ if {[regsub ^/$autoDir $prefix {} prefix] != 0} {
+ break
+ }
+ }
+ }
+ }
+ }
+
+ set curFilter $itk_option(-mask);
+ $itk_component(filter) delete 0 end
+ $itk_component(filter) insert 0 [file join $_pwd $itk_option(-mask)]
+
+ #
+ # Make sure the right most text is visable.
+ #
+ $itk_component(filter) xview moveto 1
+}
+
+# ------------------------------------------------------------------
+# OPTION: -directory
+#
+# Specifies the initial default directory.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::directory {
+ if {$itk_option(-directory) != {}} {
+ if {! [file exists $itk_option(-directory)]} {
+ error "bad directory option \"$itk_option(-directory)\":\
+ directory does not exist"
+ }
+
+ set olddir [pwd]
+ cd $itk_option(-directory)
+ set _pwd [pwd]
+ cd $olddir
+
+ configure -mask $itk_option(-mask)
+ _selectFilter
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -automount
+#
+# Specifies list of directory prefixes to ignore. Typically, this
+# option would be used with values such as:
+# -automount {export tmp_mnt}
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::automount {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -nomatchstring
+#
+# Specifies the string to be displayed in the files list should
+# not regular files exist in the directory.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::nomatchstring {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -dirsearchcommand
+#
+# Specifies a command to be executed to perform a directory search.
+# The command will receive the current working directory and filter
+# mask as arguments. The command should return a list of files which
+# will be placed into the directory list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::dirsearchcommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -filesearchcommand
+#
+# Specifies a command to be executed to perform a file search.
+# The command will receive the current working directory and filter
+# mask as arguments. The command should return a list of files which
+# will be placed into the file list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::filesearchcommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectioncommand
+#
+# Specifies a command to be executed upon pressing return in the
+# selection entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::selectioncommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -filtercommand
+#
+# Specifies a command to be executed upon pressing return in the
+# filter entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::filtercommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectdircommand
+#
+# Specifies a command to be executed following selection of a
+# directory in the directory list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::selectdircommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectfilecommand
+#
+# Specifies a command to be executed following selection of a
+# file in the files list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::selectfilecommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -invalid
+#
+# Specify a command to executed should the filter contents be
+# proven invalid.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::invalid {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -filetype
+#
+# Specify the type of files which may appear in the file list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::filetype {
+ switch $itk_option(-filetype) {
+ regular -
+ directory -
+ any {
+ }
+ default {
+ error "bad filetype option \"$itk_option(-filetype)\":\
+ should be regular, directory, or any"
+ }
+ }
+
+ _updateLists
+}
+
+# ------------------------------------------------------------------
+# OPTION: -width
+#
+# Specifies the width of the file selection box. The value may be
+# specified in any of the forms acceptable to Tk_GetPixels.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::width {
+ #
+ # The width option was added to the hull in the constructor.
+ # So, any width value given is passed automatically to the
+ # hull. All we have to do is play with the propagation.
+ #
+ if {$itk_option(-width) != 0} {
+ set propagate 0
+ } else {
+ set propagate 1
+ }
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $itk_component(hull)] != $propagate} {
+ grid propagate $itk_component(hull) $propagate
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -height
+#
+# Specifies the height of the file selection box. The value may be
+# specified in any of the forms acceptable to Tk_GetPixels.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Fileselectionbox::height {
+ #
+ # The height option was added to the hull in the constructor.
+ # So, any height value given is passed automatically to the
+ # hull. All we have to do is play with the propagation.
+ #
+ if {$itk_option(-height) != 0} {
+ set propagate 0
+ } else {
+ set propagate 1
+ }
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $itk_component(hull)] != $propagate} {
+ grid propagate $itk_component(hull) $propagate
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Returns the path name of the child site widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::childsite {} {
+ return $itk_component(childsite)
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Returns the current selection.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::get {} {
+ return [$itk_component(selection) get]
+}
+
+# ------------------------------------------------------------------
+# METHOD: filter
+#
+# The user has pressed Return in the filter. Make sure the contents
+# contain a valid directory before setting default to directory.
+# Use the invalid option to warn the user of any problems.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::filter {} {
+ set newdir [file dirname [$itk_component(filter) get]]
+
+ if {! [file exists $newdir]} {
+ uplevel #0 "$itk_option(-invalid)"
+ return
+ }
+
+ set _pwd $newdir;
+ if {$_pwd == "."} {set _pwd [pwd]};
+
+ _updateLists
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _updateLists ?now?
+#
+# Updates the contents of both the file and directory lists, as well
+# resets the positions of the filter, and lists.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_updateLists {{when "later"}} {
+ switch -- $when {
+ later {
+ if {$_updateToken == ""} {
+ set _updateToken [after idle [itcl::code $this _updateLists now]]
+ }
+ }
+ now {
+ if {$itk_option(-dirson)} {_setDirList}
+ if {$itk_option(-fileson)} {_setFileList}
+
+ if {$itk_option(-filteron)} {
+ _setFilter
+ }
+ if {$itk_option(-selectionon)} {
+ $itk_component(selection) icursor end
+ }
+ if {$itk_option(-dirson)} {
+ $itk_component(dirs) justify left
+ }
+ if {$itk_option(-fileson)} {
+ $itk_component(files) justify left
+ }
+ set _updateToken ""
+ }
+ default {
+ error "bad option \"$when\": should be later or now"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setFilter
+#
+# Set the filter to the current selection in the directory list plus
+# any existing mask in the filter. Translate the two special cases
+# of '.', and '..' directory names to full path names..
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_setFilter {} {
+ global tcl_platform
+ set prefix [$itk_component(dirs) getcurselection]
+ set curFilter [file tail [$itk_component(filter) get]]
+
+ while {[regexp {\.$} $prefix]} {
+ if {[file tail $prefix] == "."} {
+ if {$prefix == "."} {
+ if {$_pwd == "."} {
+ set _pwd [pwd]
+ } elseif {$_pwd == ".."} {
+ set _pwd [file dirname [pwd]]
+ }
+ set prefix $_pwd
+ } else {
+ set prefix [file dirname $prefix]
+ }
+ } elseif {[file tail $prefix] == ".."} {
+ if {$prefix != ".."} {
+ set prefix [file dirname [file dirname $prefix]]
+ } else {
+ if {$_pwd == "."} {
+ set _pwd [pwd]
+ } elseif {$_pwd == ".."} {
+ set _pwd [file dirname [pwd]]
+ }
+ set prefix [file dirname $_pwd]
+ }
+ } else {
+ break
+ }
+ }
+
+ if { [file pathtype $prefix] != "absolute" } {
+ set prefix [file join $_pwd $prefix]
+ }
+
+ #
+ # Remove automounter paths.
+ #
+ if {$tcl_platform(platform) == "unix"} {
+ if {$itk_option(-automount) != {}} {
+ foreach autoDir $itk_option(-automount) {
+ # Use catch because we can't be sure exactly what strings
+ # were passed into the -automount option
+ catch {
+ if {[regsub ^/$autoDir $prefix {} prefix] != 0} {
+ break
+ }
+ }
+ }
+ }
+ }
+
+ $itk_component(filter) delete 0 end
+ $itk_component(filter) insert 0 [file join $prefix $curFilter]
+
+ #
+ # Make sure insertion cursor is at the end.
+ #
+ $itk_component(filter) icursor end
+
+ #
+ # Make sure the right most text is visable.
+ #
+ $itk_component(filter) xview moveto 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setSelection
+#
+# Set the contents of the selection entry to either the current
+# selection of the file or directory list dependent on which lists
+# are currently mapped. For the file list, avoid seleciton of the
+# no match string. As for the directory list, translate file names.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_setSelection {} {
+ global tcl_platform
+ $itk_component(selection) delete 0 end
+
+ if {$itk_option(-fileson)} {
+ set selection [$itk_component(files) getcurselection]
+
+ if {$selection != $itk_option(-nomatchstring)} {
+ if {[file pathtype $selection] != "absolute"} {
+ set selection [file join $_pwd $selection]
+ }
+
+ #
+ # Remove automounter paths.
+ #
+ if {$tcl_platform(platform) == "unix"} {
+ if {$itk_option(-automount) != {}} {
+ foreach autoDir $itk_option(-automount) {
+ # Use catch because we can't be sure exactly what strings
+ # were passed into the -automount option
+ catch {
+ if {[regsub ^/$autoDir $selection {} selection] != 0} {
+ break
+ }
+ }
+ }
+ }
+ }
+
+ $itk_component(selection) insert 0 $selection
+ } else {
+ $itk_component(files) selection clear 0 end
+ }
+
+ } else {
+ set selection [$itk_component(dirs) getcurselection]
+
+ if {[file tail $selection] == "."} {
+ if {$selection != "."} {
+ set selection [file dirname $selection]
+ } else {
+ set selection $_pwd
+ }
+ } elseif {[file tail $selection] == ".."} {
+ if {$selection != ".."} {
+ set selection [file dirname [file dirname $selection]]
+ } else {
+ set selection [file join $_pwd ..]
+ }
+ } else {
+ set selection [file join $_pwd $selection]
+ }
+
+ #
+ # Remove automounter paths.
+ #
+ if {$tcl_platform(platform) == "unix"} {
+ if {$itk_option(-automount) != {}} {
+ foreach autoDir $itk_option(-automount) {
+ # Use catch because we can't be sure exactly what strings
+ # were passed into the -automount option
+ catch {
+ if {[regsub ^/$autoDir $selection {} selection] != 0} {
+ break
+ }
+ }
+ }
+ }
+ }
+
+ $itk_component(selection) delete 0 end
+ $itk_component(selection) insert 0 $selection
+ }
+
+ $itk_component(selection) icursor end
+
+ #
+ # Make sure the right most text is visable.
+ #
+ $itk_component(selection) xview moveto 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setDirList
+#
+# Clear the directory list and dependent on whether the user has
+# defined their own search procedure or not fill the list with their
+# results or those of a glob. Select the first element if it exists.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_setDirList {} {
+ $itk_component(dirs) clear
+
+ if {$itk_option(-dirsearchcommand) == {}} {
+ foreach i [lsort [glob -nocomplain \
+ [file join $_pwd .*] [file join $_pwd *]]] {
+ if {[file isdirectory $i]} {
+ $itk_component(dirs) insert end [file tail "$i"]
+ }
+ }
+
+ } else {
+ set mask [file tail [$itk_component(filter) get]]
+
+ foreach file [uplevel #0 $itk_option(-dirsearchcommand) $_pwd $mask] {
+ $itk_component(dirs) insert end $file
+ }
+ }
+
+ if {[$itk_component(dirs) size]} {
+ $itk_component(dirs) selection clear 0 end
+ $itk_component(dirs) selection set 0
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setFileList
+#
+# Clear the file list and dependent on whether the user has defined
+# their own search procedure or not fill the list with their results
+# or those of a 'glob'. If the files list has no contents, then set
+# the files list to the 'nomatchstring'. Clear all selections.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_setFileList {} {
+ $itk_component(files) clear
+ set mask [file tail [$itk_component(filter) get]]
+
+ if {$itk_option(-filesearchcommand) == {}} {
+ if {$mask == "*"} {
+ set files [lsort [glob -nocomplain \
+ [file join $_pwd .*] [file join $_pwd *]]]
+ } else {
+ set files [lsort [glob -nocomplain [file join $_pwd $mask]]]
+ }
+
+ foreach i $files {
+ if {($itk_option(-filetype) == "regular" && \
+ ! [file isdirectory $i]) || \
+ ($itk_option(-filetype) == "directory" && \
+ [file isdirectory $i]) || \
+ ($itk_option(-filetype) == "any")} {
+ $itk_component(files) insert end [file tail "$i"]
+ }
+ }
+
+ } else {
+ foreach file [uplevel #0 $itk_option(-filesearchcommand) $_pwd $mask] {
+ $itk_component(files) insert end $file
+ }
+ }
+
+ if {[$itk_component(files) size] == 0} {
+ if {$itk_option(-nomatchstring) != {}} {
+ $itk_component(files) insert end $itk_option(-nomatchstring)
+ }
+ }
+
+ $itk_component(files) selection clear 0 end
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _selectDir
+#
+# For a selection in the directory list, set the filter and possibly
+# the selection entry based on the fileson option.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_selectDir {} {
+ _setFilter
+
+ if {$itk_option(-fileson)} {} {
+ _setSelection
+ }
+
+ if {$itk_option(-selectdircommand) != {}} {
+ uplevel #0 $itk_option(-selectdircommand)
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _dblSelectDir
+#
+# For a double click event in the directory list, select the
+# directory, set the default to the selection, and update both the
+# file and directory lists.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_dblSelectDir {} {
+ filter
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _selectFile
+#
+# The user has selected a file. Put the current selection in the
+# file list in the selection entry widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_selectFile {} {
+ _setSelection
+
+ if {$itk_option(-selectfilecommand) != {}} {
+ uplevel #0 $itk_option(-selectfilecommand)
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _selectSelection
+#
+# The user has pressed Return in the selection entry widget. Call
+# the defined selection command if it exists.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_selectSelection {} {
+ if {$itk_option(-selectioncommand) != {}} {
+ uplevel #0 $itk_option(-selectioncommand)
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _selectFilter
+#
+# The user has pressed Return in the filter entry widget. Call the
+# defined selection command if it exists, otherwise just filter.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_selectFilter {} {
+ if {$itk_option(-filtercommand) != {}} {
+ uplevel #0 $itk_option(-filtercommand)
+ } else {
+ filter
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _packComponents
+#
+# Pack the selection, items, and child site widgets based on options.
+# Using the -in option of pack, put the childsite around the frame
+# in the hull for n, s, e, and w positions. Make sure and raise
+# the child site since using the 'in' option may obscure the site.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_packComponents {{when "later"}} {
+ if {$when == "later"} {
+ if {$_packToken == ""} {
+ set _packToken [after idle [itcl::code $this _packComponents now]]
+ }
+ return
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ set _packToken ""
+
+ #
+ # Forget about any previous placements via the grid and
+ # reset all the possible minsizes and weights for all
+ # the rows and columns.
+ #
+ foreach component {childsite filter dirs files selection} {
+ grid forget $itk_component($component)
+ }
+
+ for {set row 0} {$row < 6} {incr row} {
+ grid rowconfigure $_interior $row -minsize 0 -weight 0
+ }
+
+ for {set col 0} {$col < 4} {incr col} {
+ grid columnconfigure $_interior $col -minsize 0 -weight 0
+ }
+
+ #
+ # Place all the components based on the childsite poisition
+ # option.
+ #
+ switch $itk_option(-childsitepos) {
+ n { _nPos }
+
+ w { _wPos }
+
+ s { _sPos }
+
+ e { _ePos }
+
+ center { _centerPos }
+
+ top { _topPos }
+
+ bottom { _bottomPos }
+
+ default {
+ error "bad childsitepos option \"$itk_option(-childsitepos)\":\
+ should be n, e, s, w, center, top, or bottom"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _nPos
+#
+# Position the childsite to the north and all the other components
+# appropriately based on the individual "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_nPos {} {
+ grid $itk_component(childsite) -row 0 -column 0 \
+ -columnspan 3 -rowspan 1 -sticky nsew
+
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 1 -column 0 \
+ -columnspan 3 -sticky ew
+ grid rowconfigure $_interior 2 -minsize 7
+ }
+
+ if {$itk_option(-dirson)} {
+ grid $itk_component(dirs) -row 3 -column 0 \
+ -columnspan 1 -sticky nsew
+ }
+ if {$itk_option(-fileson)} {
+ grid $itk_component(files) -row 3 -column 2 \
+ -columnspan 1 -sticky nsew
+ }
+ if {$itk_option(-dirson)} {
+ if {$itk_option(-fileson)} {
+ grid columnconfigure $_interior 1 -minsize 7
+ } else {
+ grid configure $itk_component(dirs) -columnspan 3 -column 0
+ }
+ } else {
+ if {$itk_option(-fileson)} {
+ grid configure $itk_component(files) -columnspan 3 -column 0
+ }
+ }
+
+ grid rowconfigure $_interior 3 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 4 -minsize 7
+ grid $itk_component(selection) -row 5 -column 0 \
+ -columnspan 3 -sticky ew
+ }
+
+ grid columnconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 2 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _sPos
+#
+# Position the childsite to the south and all the other components
+# appropriately based on the individual "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_sPos {} {
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 0 \
+ -columnspan 3 -sticky ew
+ grid rowconfigure $_interior 1 -minsize 7
+ }
+
+ if {$itk_option(-dirson)} {
+ grid $itk_component(dirs) -row 2 -column 0 \
+ -columnspan 1 -sticky nsew
+ }
+ if {$itk_option(-fileson)} {
+ grid $itk_component(files) -row 2 -column 2 \
+ -columnspan 1 -sticky nsew
+ }
+ if {$itk_option(-dirson)} {
+ if {$itk_option(-fileson)} {
+ grid columnconfigure $_interior 1 -minsize 7
+ } else {
+ grid configure $itk_component(dirs) -columnspan 3 -column 0
+ }
+ } else {
+ if {$itk_option(-fileson)} {
+ grid configure $itk_component(files) -columnspan 3 -column 0
+ }
+ }
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 3 -minsize 7
+ grid $itk_component(selection) -row 4 -column 0 \
+ -columnspan 3 -sticky ew
+ }
+
+ grid $itk_component(childsite) -row 5 -column 0 \
+ -columnspan 3 -rowspan 1 -sticky nsew
+ grid columnconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 2 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _ePos
+#
+# Position the childsite to the east and all the other components
+# appropriately based on the individual "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_ePos {} {
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 0 \
+ -columnspan 3 -sticky ew
+ grid rowconfigure $_interior 1 -minsize 7
+ }
+
+ if {$itk_option(-dirson)} {
+ grid $itk_component(dirs) -row 2 -column 0 \
+ -columnspan 1 -sticky nsew
+ }
+ if {$itk_option(-fileson)} {
+ grid $itk_component(files) -row 2 -column 2 \
+ -columnspan 1 -sticky nsew
+ }
+ if {$itk_option(-dirson)} {
+ if {$itk_option(-fileson)} {
+ grid columnconfigure $_interior 1 -minsize 7
+ } else {
+ grid configure $itk_component(dirs) -columnspan 3 -column 0
+ }
+ } else {
+ if {$itk_option(-fileson)} {
+ grid configure $itk_component(files) -columnspan 3 -column 0
+ }
+ }
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 3 -minsize 7
+ grid $itk_component(selection) -row 4 -column 0 \
+ -columnspan 3 -sticky ew
+ }
+
+ grid $itk_component(childsite) -row 0 -column 3 \
+ -rowspan 5 -columnspan 1 -sticky nsew
+ grid columnconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 2 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _wPos
+#
+# Position the childsite to the west and all the other components
+# appropriately based on the individual "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_wPos {} {
+ grid $itk_component(childsite) -row 0 -column 0 \
+ -rowspan 5 -columnspan 1 -sticky nsew
+
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 1 \
+ -columnspan 3 -sticky ew
+ grid rowconfigure $_interior 1 -minsize 7
+ }
+
+ if {$itk_option(-dirson)} {
+ grid $itk_component(dirs) -row 2 -column 1 \
+ -columnspan 1 -sticky nsew
+ }
+ if {$itk_option(-fileson)} {
+ grid $itk_component(files) -row 2 -column 3 \
+ -columnspan 1 -sticky nsew
+ }
+ if {$itk_option(-dirson)} {
+ if {$itk_option(-fileson)} {
+ grid columnconfigure $_interior 2 -minsize 7
+ } else {
+ grid configure $itk_component(dirs) -columnspan 3 -column 1
+ }
+ } else {
+ if {$itk_option(-fileson)} {
+ grid configure $itk_component(files) -columnspan 3 -column 1
+ }
+ }
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 3 -minsize 7
+ grid $itk_component(selection) -row 4 -column 1 \
+ -columnspan 3 -sticky ew
+ }
+
+ grid columnconfigure $_interior 1 -weight 1
+ grid columnconfigure $_interior 3 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _topPos
+#
+# Position the childsite below the filter but above the lists and
+# all the other components appropriately based on the individual
+# "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_topPos {} {
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 0 \
+ -columnspan 3 -sticky ew
+ }
+
+ grid $itk_component(childsite) -row 1 -column 0 \
+ -columnspan 3 -rowspan 1 -sticky nsew
+
+ if {$itk_option(-dirson)} {
+ grid $itk_component(dirs) -row 2 -column 0 -sticky nsew
+ }
+ if {$itk_option(-fileson)} {
+ grid $itk_component(files) -row 2 -column 2 -sticky nsew
+ }
+ if {$itk_option(-dirson)} {
+ if {$itk_option(-fileson)} {
+ grid columnconfigure $_interior 1 -minsize 7
+ } else {
+ grid configure $itk_component(dirs) -columnspan 3 -column 0
+ }
+ } else {
+ if {$itk_option(-fileson)} {
+ grid configure $itk_component(files) -columnspan 3 -column 0
+ }
+ }
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 3 -minsize 7
+ grid $itk_component(selection) -row 4 -column 0 \
+ -columnspan 3 -sticky ew
+ }
+
+ grid columnconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 2 -weight 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _centerPos
+#
+# Position the childsite between the lists and all the other
+# components appropriately based on the individual "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_centerPos {} {
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 0 \
+ -columnspan 3 -sticky ew
+ grid rowconfigure $_interior 1 -minsize 7
+ }
+
+ if {$itk_option(-dirson)} {
+ grid $itk_component(dirs) -row 2 -column 0 \
+ -columnspan 1 -sticky nsew
+ }
+ if {$itk_option(-fileson)} {
+ grid $itk_component(files) -row 2 -column 2 \
+ -columnspan 1 -sticky nsew
+ }
+ grid $itk_component(childsite) -row 2 \
+ -columnspan 1 -rowspan 1 -sticky nsew
+
+ if {$itk_option(-dirson)} {
+ if {$itk_option(-fileson)} {
+ grid configure $itk_component(childsite) -column 1
+ grid columnconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 2 -weight 1
+
+ } else {
+ grid configure $itk_component(dirs) -columnspan 2 -column 0
+ grid configure $itk_component(childsite) -column 2
+ grid columnconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 1 -weight 1
+ }
+ } else {
+ grid configure $itk_component(childsite) -column 0
+ if {$itk_option(-fileson)} {
+ grid configure $itk_component(files) -columnspan 2 \
+ -column 1
+ grid columnconfigure $_interior 1 -weight 1
+ grid columnconfigure $_interior 2 -weight 1
+ } else {
+ grid columnconfigure $_interior 0 -weight 1
+ }
+ }
+
+ grid rowconfigure $_interior 2 -weight 1
+
+ if {$itk_option(-selectionon)} {
+ grid rowconfigure $_interior 3 -minsize 7
+ grid $itk_component(selection) -row 4 -column 0 \
+ -columnspan 3 -sticky ew
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _bottomPos
+#
+# Position the childsite below the lists and above the selection
+# and all the other components appropriately based on the individual
+# "on" options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectionbox::_bottomPos {} {
+ if {$itk_option(-filteron)} {
+ grid $itk_component(filter) -row 0 -column 0 \
+ -columnspan 3 -sticky ew
+ grid rowconfigure $_interior 1 -minsize 7
+ }
+
+ if {$itk_option(-dirson)} {
+ grid $itk_component(dirs) -row 2 -column 0 -sticky nsew
+ }
+ if {$itk_option(-fileson)} {
+ grid $itk_component(files) -row 2 -column 2 -sticky nsew
+ }
+ if {$itk_option(-dirson)} {
+ if {$itk_option(-fileson)} {
+ grid columnconfigure $_interior 1 -minsize 7
+ } else {
+ grid configure $itk_component(dirs) -columnspan 3 -column 0
+ }
+ } else {
+ if {$itk_option(-fileson)} {
+ grid configure $itk_component(files) -columnspan 3 -column 0
+ }
+ }
+ grid rowconfigure $_interior 2 -weight 1
+
+ grid $itk_component(childsite) -row 3 -column 0 \
+ -columnspan 3 -rowspan 1 -sticky nsew
+
+ if {$itk_option(-selectionon)} {
+ grid $itk_component(selection) -row 4 -column 0 \
+ -columnspan 3 -sticky ew
+ }
+
+ grid columnconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 2 -weight 1
+}
diff --git a/iwidgets/generic/fileselectiondialog.itk b/iwidgets/generic/fileselectiondialog.itk
new file mode 100644
index 00000000000..d24ce2dfe9a
--- /dev/null
+++ b/iwidgets/generic/fileselectiondialog.itk
@@ -0,0 +1,181 @@
+#
+# Fileselectiondialog
+# ----------------------------------------------------------------------
+# Implements a file selection box similar to the OSF/Motif standard
+# file selection dialog composite widget. The Fileselectiondialog is
+# derived from the Dialog class and is composed of a FileSelectionBox
+# with attributes set to manipulate the dialog buttons.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Fileselectiondialog {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -insertbackground -insertborderwidth -insertofftime -insertontime \
+ -insertwidth -jump -labelfont -modality -selectbackground \
+ -selectborderwidth -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# FILESELECTIONDIALOG
+# ------------------------------------------------------------------
+itcl::class iwidgets::Fileselectiondialog {
+ inherit iwidgets::Dialog
+
+ constructor {args} {}
+
+ public {
+ method childsite {}
+ method get {}
+ method filter {}
+ }
+
+ protected method _dbldir {}
+}
+
+#
+# Provide a lowercased access method for the Fileselectiondialog class.
+#
+proc ::iwidgets::fileselectiondialog {pathName args} {
+ uplevel ::iwidgets::Fileselectiondialog $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Fileselectiondialog.borderWidth 2 widgetDefault
+
+option add *Fileselectiondialog.title "File Selection Dialog" widgetDefault
+
+option add *Fileselectiondialog.width 350 widgetDefault
+option add *Fileselectiondialog.height 400 widgetDefault
+
+option add *Fileselectiondialog.master "." widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectiondialog::constructor {args} {
+ component hull configure -borderwidth 0
+ itk_option add hull.width hull.height
+
+ #
+ # Turn off pack propagation for the hull widget so the width
+ # and height options become active.
+ #
+ pack propagate $itk_component(hull) no
+
+ #
+ # Instantiate a file selection box widget.
+ #
+ itk_component add fsb {
+ iwidgets::Fileselectionbox $itk_interior.fsb -width 150 -height 150 \
+ -selectioncommand [itcl::code $this invoke] \
+ -selectdircommand [itcl::code $this default Apply] \
+ -selectfilecommand [itcl::code $this default OK]
+ } {
+ usual
+
+ keep -labelfont -childsitepos -directory -dirslabel \
+ -dirsearchcommand -dirson -fileslabel -fileson \
+ -filesearchcommand -filterlabel -filteron \
+ -filetype -invalid -mask -nomatchstring \
+ -selectionlabel -selectionon
+ }
+ grid $itk_component(fsb) -sticky nsew
+ grid rowconfigure $itk_interior 0 -weight 1
+ grid columnconfigure $itk_interior 0 -weight 1
+
+ $itk_component(fsb) component filter configure \
+ -focuscommand [itcl::code $this default Apply]
+ $itk_component(fsb) component selection configure \
+ -focuscommand [itcl::code $this default OK]
+ $itk_component(fsb) component dirs configure \
+ -dblclickcommand [itcl::code $this _dbldir]
+ $itk_component(fsb) component files configure \
+ -dblclickcommand [itcl::code $this invoke]
+
+ buttonconfigure Apply -text "Filter" \
+ -command [itcl::code $itk_component(fsb) filter]
+
+ set itk_interior [$itk_component(fsb) childsite]
+
+ hide Help
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Thinwrapped method of file selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectiondialog::childsite {} {
+ return [$itk_component(fsb) childsite]
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Thinwrapped method of file selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectiondialog::get {} {
+ return [$itk_component(fsb) get]
+}
+
+# ------------------------------------------------------------------
+# METHOD: filter
+#
+# Thinwrapped method of file selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectiondialog::filter {} {
+ return [$itk_component(fsb) filter]
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _dbldir
+#
+# Double select in directory list. If the files list is on then
+# make the default button the filter and invoke. If not, just invoke.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Fileselectiondialog::_dbldir {} {
+ if {$itk_option(-fileson)} {
+ default Apply
+ }
+
+ invoke
+}
+
diff --git a/iwidgets/generic/finddialog.itk b/iwidgets/generic/finddialog.itk
new file mode 100644
index 00000000000..7bf38f10ee8
--- /dev/null
+++ b/iwidgets/generic/finddialog.itk
@@ -0,0 +1,488 @@
+#
+# Finddialog
+# ----------------------------------------------------------------------
+# This class implements a dialog for searching text. It prompts the
+# user for a search string and the method of searching which includes
+# case sensitive, regular expressions, backwards, and all.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) RCS: $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1996 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 Finddialog {
+ keep -background -cursor -foreground -selectcolor
+}
+
+# ------------------------------------------------------------------
+# IPRFINDDIALOG
+# ------------------------------------------------------------------
+itcl::class ::iwidgets::Finddialog {
+ inherit iwidgets::Dialogshell
+
+ constructor {args} {}
+
+ itk_option define -selectcolor selectColor Background {}
+ itk_option define -clearcommand clearCommand Command {}
+ itk_option define -matchcommand matchCommand Command {}
+ itk_option define -patternbackground patternBackground Background \#707070
+ itk_option define -patternforeground patternForeground Foreground White
+ itk_option define -searchbackground searchBackground Background \#c4c4c4
+ itk_option define -searchforeground searchForeground Foreground Black
+ itk_option define -textwidget textWidget TextWidget {}
+
+ public {
+ method clear {}
+ method find {}
+ }
+
+ protected {
+ method _get {setting}
+ method _textExists {}
+
+ common _optionValues ;# Current settings of check buttons.
+ common _searchPoint ;# Starting location for searches
+ common _matchLen ;# Matching pattern string length
+ }
+}
+
+#
+# Provide a lowercased access method for the ::finddialog class.
+#
+proc ::iwidgets::finddialog {pathName args} {
+ uplevel ::iwidgets::Finddialog $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Finddialog.title "Find" widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body ::iwidgets::Finddialog::constructor {args} {
+ #
+ # Add the find pattern entryfield.
+ #
+ itk_component add pattern {
+ iwidgets::Entryfield $itk_interior.pattern -labeltext "Find:"
+ }
+ bind [$itk_component(pattern) component entry] \
+ <Return> "[itcl::code $this invoke]; break"
+
+ #
+ # Add the find all checkbutton.
+ #
+ itk_component add all {
+ checkbutton $itk_interior.all \
+ -variable [itcl::scope _optionValues($this-all)] \
+ -text "All"
+ }
+
+ #
+ # Add the case consideration checkbutton.
+ #
+ itk_component add case {
+ checkbutton $itk_interior.case \
+ -variable [itcl::scope _optionValues($this-case)] \
+ -text "Consider Case"
+ }
+
+ #
+ # Add the regular expression checkbutton.
+ #
+ itk_component add regexp {
+ checkbutton $itk_interior.regexp \
+ -variable [itcl::scope _optionValues($this-regexp)] \
+ -text "Use Regular Expression"
+ }
+
+ #
+ # Add the find backwards checkbutton.
+ #
+ itk_component add backwards {
+ checkbutton $itk_interior.backwards \
+ -variable [itcl::scope _optionValues($this-backwards)] \
+ -text "Find Backwards"
+ }
+
+ #
+ # Add the find, clear, and close buttons, making find be the default.
+ #
+ add Find -text Find -command [itcl::code $this find]
+ add Clear -text Clear -command [itcl::code $this clear]
+ add Close -text Close -command [itcl::code $this deactivate 0]
+
+ default Find
+
+ #
+ # Use the grid to layout the components.
+ #
+ grid $itk_component(pattern) -row 0 -column 0 \
+ -padx 10 -pady 10 -columnspan 4 -sticky ew
+ grid $itk_component(all) -row 1 -column 0
+ grid $itk_component(case) -row 1 -column 1
+ grid $itk_component(regexp) -row 1 -column 2
+ grid $itk_component(backwards) -row 1 -column 3
+
+ grid columnconfigure $itk_interior 0 -weight 1
+ grid columnconfigure $itk_interior 1 -weight 1
+ grid columnconfigure $itk_interior 2 -weight 1
+ grid columnconfigure $itk_interior 3 -weight 1
+
+ #
+ # Initialize all the configuration options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -clearcommand
+#
+# Specifies a command to be invoked following a clear operation.
+# The command is meant to be a means of notification that the
+# clear has taken place and allow other actions to take place such
+# as disabling a find again menu.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Finddialog::clearcommand {}
+
+# ------------------------------------------------------------------
+# OPTION: -matchcommand
+#
+# Specifies a command to be invoked following a find operation.
+# The command is called with a match point as an argument. Should
+# a match not be found the match point is {}.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Finddialog::matchcommand {}
+
+# ------------------------------------------------------------------
+# OPTION: -patternbackground
+#
+# Specifies the background color of the text matching the search
+# pattern. It may have any of the forms accepted by Tk_GetColor.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Finddialog::patternbackground {}
+
+# ------------------------------------------------------------------
+# OPTION: -patternforeground
+#
+# Specifies the foreground color of the pattern matching a search
+# operation. It may have any of the forms accepted by Tk_GetColor.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Finddialog::patternforeground {}
+
+# ------------------------------------------------------------------
+# OPTION: -searchforeground
+#
+# Specifies the foreground color of the line containing the matching
+# pattern from a search operation. It may have any of the forms
+# accepted by Tk_GetColor.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Finddialog::searchforeground {}
+
+# ------------------------------------------------------------------
+# OPTION: -searchbackground
+#
+# Specifies the background color of the line containing the matching
+# pattern from a search operation. It may have any of the forms
+# accepted by Tk_GetColor.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Finddialog::searchbackground {}
+
+# ------------------------------------------------------------------
+# OPTION: -textwidget
+#
+# Specifies the scrolledtext or text widget to be searched.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Finddialog::textwidget {
+ if {$itk_option(-textwidget) != {}} {
+ set _searchPoint($itk_option(-textwidget)) 1.0
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: clear
+#
+# Clear the pattern entryfield and the indicators.
+# ------------------------------------------------------------------
+itcl::body ::iwidgets::Finddialog::clear {} {
+ $itk_component(pattern) clear
+
+ if {[_textExists]} {
+ set _searchPoint($itk_option(-textwidget)) 1.0
+
+ $itk_option(-textwidget) tag remove search-line 1.0 end
+ $itk_option(-textwidget) tag remove search-pattern 1.0 end
+ }
+
+ if {$itk_option(-clearcommand) != {}} {
+ eval $itk_option(-clearcommand)
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: find
+#
+# Search for a specific text string in the text widget given by
+# the -textwidget option. Should this option not be set to an
+# existing widget, then a quick exit is made.
+# ------------------------------------------------------------------
+itcl::body ::iwidgets::Finddialog::find {} {
+ if {! [_textExists]} {
+ return
+ }
+
+ #
+ # Clear any existing indicators in the text widget.
+ #
+ $itk_option(-textwidget) tag remove search-line 1.0 end
+ $itk_option(-textwidget) tag remove search-pattern 1.0 end
+
+ #
+ # Make sure the search pattern isn't just blank. If so, skip this.
+ #
+ set pattern [_get pattern]
+
+ if {[string trim $pattern] == ""} {
+ return
+ }
+
+ #
+ # After clearing out any old highlight indicators from a previous
+ # search, we'll be building our search command piece-meal based on
+ # the current settings of the checkbuttons in the find dialog. The
+ # first we'll add is a variable to catch the count of the length
+ # of the string matching the pattern.
+ #
+ set precmd "$itk_option(-textwidget) search \
+ -count [list [itcl::scope _matchLen($this)]]"
+
+ if {! [_get case]} {
+ append precmd " -nocase"
+ }
+
+ if {[_get regexp]} {
+ append precmd " -regexp"
+ } else {
+ append precmd " -exact"
+ }
+
+ #
+ # If we are going to find all matches, then the start point for
+ # the search will be the beginning of the text; otherwise, we'll
+ # use the last known starting point +/- a character depending on
+ # the direction.
+ #
+ if {[_get all]} {
+ set _searchPoint($itk_option(-textwidget)) 1.0
+ } else {
+ if {[_get backwards]} {
+ append precmd " -backwards"
+ } else {
+ append precmd " -forwards"
+ }
+ }
+
+ #
+ # Get the pattern to be matched and add it to the search command.
+ # Since it may contain embedded spaces, we'll wrap it in a list.
+ #
+ append precmd " [list $pattern]"
+
+ #
+ # If the search is for all matches, then we'll be performing the
+ # search until no more matches are found; otherwise, we'll break
+ # out of the loop after one search.
+ #
+ while {1} {
+ if {[_get all]} {
+ set postcmd " $_searchPoint($itk_option(-textwidget)) end"
+
+ } else {
+ set postcmd " $_searchPoint($itk_option(-textwidget))"
+ }
+
+ #
+ # Create the final search command out of the pre and post parts
+ # and evaluate it which returns the location of the matching string.
+ #
+ set cmd {}
+ append cmd $precmd $postcmd
+
+ if {[catch {eval $cmd} matchPoint] != 0} {
+ set _searchPoint($itk_option(-textwidget)) 1.0
+ return {}
+ }
+
+ #
+ # If a match exists, then we'll make this spot be the new starting
+ # position. Then we'll tag the line and the pattern in the line.
+ # The foreground and background settings will lite these positions
+ # in the text widget up.
+ #
+ if {$matchPoint != {}} {
+ set _searchPoint($itk_option(-textwidget)) $matchPoint
+
+ $itk_option(-textwidget) tag add search-line \
+ "$_searchPoint($itk_option(-textwidget)) linestart" \
+ "$_searchPoint($itk_option(-textwidget))"
+ $itk_option(-textwidget) tag add search-line \
+ "$_searchPoint($itk_option(-textwidget)) + \
+ $_matchLen($this) chars" \
+ "$_searchPoint($itk_option(-textwidget)) lineend"
+ $itk_option(-textwidget) tag add search-pattern \
+ $_searchPoint($itk_option(-textwidget)) \
+ "$_searchPoint($itk_option(-textwidget)) + \
+ $_matchLen($this) chars"
+ }
+
+ #
+ # Set the search point for the next time through to be one
+ # character more or less from the current search point based
+ # on the direction.
+ #
+ if {[_get all] || ! [_get backwards]} {
+ set _searchPoint($itk_option(-textwidget)) \
+ [$itk_option(-textwidget) index \
+ "$_searchPoint($itk_option(-textwidget)) + 1c"]
+ } else {
+ set _searchPoint($itk_option(-textwidget)) \
+ [$itk_option(-textwidget) index \
+ "$_searchPoint($itk_option(-textwidget)) - 1c"]
+ }
+
+ #
+ # If this isn't a find all operation or we didn't get a match, exit.
+ #
+ if {(! [_get all]) || ($matchPoint == {})} {
+ break
+ }
+ }
+
+ #
+ # Configure the colors for the search-line and search-pattern.
+ #
+ $itk_option(-textwidget) tag configure search-line \
+ -foreground $itk_option(-searchforeground)
+ $itk_option(-textwidget) tag configure search-line \
+ -background $itk_option(-searchbackground)
+ $itk_option(-textwidget) tag configure search-pattern \
+ -background $itk_option(-patternbackground)
+ $itk_option(-textwidget) tag configure search-pattern \
+ -foreground $itk_option(-patternforeground)
+
+ #
+ # Adjust the view to be the last matched position.
+ #
+ if {$matchPoint != {}} {
+ $itk_option(-textwidget) see $matchPoint
+ }
+
+ #
+ # There may be multiple matches of the pattern on a single line,
+ # so we'll set the tag priorities such that the pattern tag is higher.
+ #
+ $itk_option(-textwidget) tag raise search-pattern search-line
+
+ #
+ # If a match command is defined, then call it with the match point.
+ #
+ if {$itk_option(-matchcommand) != {}} {
+ [subst $itk_option(-matchcommand)] $matchPoint
+ }
+
+ #
+ # Return the match point to the caller so they know if we found
+ # anything and if so where
+ #
+ return $matchPoint
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _get setting
+#
+# Get the current value for the pattern, case, regexp, or backwards.
+# ------------------------------------------------------------------
+itcl::body ::iwidgets::Finddialog::_get {setting} {
+ switch $setting {
+ pattern {
+ return [$itk_component(pattern) get]
+ }
+ case {
+ return $_optionValues($this-case)
+ }
+ regexp {
+ return $_optionValues($this-regexp)
+ }
+ backwards {
+ return $_optionValues($this-backwards)
+ }
+ all {
+ return $_optionValues($this-all)
+ }
+ default {
+ error "bad get setting: \"$setting\", should be pattern,\
+ case, regexp, backwards, or all"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _textExists
+#
+# Check the validity of the text widget option. Does it exist and
+# is it of the class Text or Scrolledtext.
+# ------------------------------------------------------------------
+itcl::body ::iwidgets::Finddialog::_textExists {} {
+ if {$itk_option(-textwidget) == {}} {
+ return 0
+ }
+
+ if {! [winfo exists $itk_option(-textwidget)]} {
+ error "bad finddialog text widget value: \"$itk_option(-textwidget)\",\
+ the widget doesn't exist"
+ }
+
+ if {([winfo class $itk_option(-textwidget)] != "Text") &&
+ ([itcl::find objects -isa iwidgets::Scrolledtext *::$itk_option(-textwidget)] == "")} {
+ error "bad finddialog text widget value: \"$itk_option(-textwidget)\",\
+ must be of the class Text or based on Scrolledtext"
+ }
+
+ return 1
+}
diff --git a/iwidgets/generic/hierarchy.itk b/iwidgets/generic/hierarchy.itk
new file mode 100644
index 00000000000..3bb8f3c0509
--- /dev/null
+++ b/iwidgets/generic/hierarchy.itk
@@ -0,0 +1,1983 @@
+# Hierarchy
+# ----------------------------------------------------------------------
+# Hierarchical data viewer. Manages a list of nodes that can be
+# expanded or collapsed. Individual nodes can be highlighted.
+# Clicking with the right mouse button on any item brings up a
+# special item menu. Clicking on the background area brings up
+# a different popup menu.
+# ----------------------------------------------------------------------
+# AUTHOR: Michael J. McLennan
+# Bell Labs Innovations for Lucent Technologies
+# mmclennan@lucent.com
+#
+# Mark L. Ulferts
+# DSC Communications
+# mulferts@austin.dsccc.com
+#
+# RCS: $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1996 Lucent Technologies
+# ======================================================================
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that the copyright notice and warranty disclaimer appear in
+# supporting documentation, and that the names of Lucent Technologies
+# any of their entities not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# Lucent Technologies disclaims all warranties with regard to this
+# software, including all implied warranties of merchantability and
+# fitness. In no event shall Lucent Technologies 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.
+#
+# ----------------------------------------------------------------------
+# Copyright (c) 1996 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 Hierarchy {
+ keep -cursor -textfont -font
+ keep -background -foreground -textbackground
+ keep -selectbackground -selectforeground
+}
+
+# ------------------------------------------------------------------
+# HIERARCHY
+# ------------------------------------------------------------------
+itcl::class iwidgets::Hierarchy {
+ inherit iwidgets::Scrolledwidget
+
+ constructor {args} {}
+
+ destructor {}
+
+ itk_option define -alwaysquery alwaysQuery AlwaysQuery 0
+ itk_option define -closedicon closedIcon Icon {}
+ itk_option define -dblclickcommand dblClickCommand Command {}
+ itk_option define -expanded expanded Expanded 0
+ itk_option define -filter filter Filter 0
+ itk_option define -font font Font \
+ -*-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*
+ itk_option define -height height Height 0
+ itk_option define -iconcommand iconCommand Command {}
+ itk_option define -icondblcommand iconDblCommand Command {}
+ itk_option define -imagecommand imageCommand Command {}
+ itk_option define -imagedblcommand imageDblCommand Command {}
+ itk_option define -imagemenuloadcommand imageMenuLoadCommand Command {}
+ itk_option define -markbackground markBackground Foreground #a0a0a0
+ itk_option define -markforeground markForeground Background Black
+ itk_option define -nodeicon nodeIcon Icon {}
+ itk_option define -openicon openIcon Icon {}
+ itk_option define -querycommand queryCommand Command {}
+ itk_option define -selectcommand selectCommand Command {}
+ itk_option define -selectbackground selectBackground Foreground #c3c3c3
+ itk_option define -selectforeground selectForeground Background Black
+ itk_option define -textmenuloadcommand textMenuLoadCommand Command {}
+ itk_option define -visibleitems visibleItems VisibleItems 80x24
+ itk_option define -width width Width 0
+
+ public {
+ method clear {}
+ method collapse {node}
+ method current {}
+ method draw {{when -now}}
+ method expand {node}
+ method expanded {node}
+ method expState { }
+ method mark {op args}
+ method prune {node}
+ method refresh {node}
+ method selection {op args}
+ method toggle {node}
+
+ method bbox {index}
+ method compare {index1 op index2}
+ method debug {args} {eval $args}
+ method delete {first {last {}}}
+ method dlineinfo {index}
+ method dump {args}
+ method get {index1 {index2 {}}}
+ method index {index}
+ method insert {args}
+ method scan {option args}
+ method search {args}
+ method see {index}
+ method tag {op args}
+ method window {option args}
+ method xview {args}
+ method yview {args}
+ }
+
+ protected {
+ method _contents {uid}
+ method _post {x y}
+ method _drawLevel {node indent}
+ method _select {x y}
+ method _deselectSubNodes {uid}
+ method _deleteNodeInfo {uid}
+ method _getParent {uid}
+ method _getHeritage {uid}
+ method _isInternalTag {tag}
+ method _iconSelect {node icon}
+ method _iconDblSelect {node icon}
+ method _imageSelect {node}
+ method _imageDblClick {node}
+ method _imagePost {node image type x y}
+ method _double {x y}
+ }
+
+ private {
+ method _configureTags {}
+
+ variable _filterCode "" ;# Compact view flag.
+ variable _hcounter 0 ;# Counter for hierarchy icons
+ variable _icons ;# Array of user icons by uid
+ variable _images ;# Array of our icons by uid
+ variable _indents ;# Array of indentation by uid
+ variable _marked ;# Array of marked nodes by uid
+ variable _markers "" ;# List of markers for level being drawn
+ variable _nodes ;# Array of subnodes by uid
+ variable _pending "" ;# Pending draw flag
+ variable _posted "" ;# List of tags at posted menu position
+ variable _selected ;# Array of selected nodes by uid
+ variable _tags ;# Array of user tags by uid
+ variable _text ;# Array of displayed text by uid
+ variable _states ;# Array of selection state by uid
+ variable _ucounter 0 ;# Counter for user icons
+ }
+}
+
+#
+# Provide a lowercased access method for the Hierarchy class.
+#
+proc ::iwidgets::hierarchy {pathName args} {
+ uplevel ::iwidgets::Hierarchy $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Hierarchy.menuCursor arrow widgetDefault
+option add *Hierarchy.labelPos n widgetDefault
+option add *Hierarchy.tabs 30 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::constructor {args} {
+ itk_option remove iwidgets::Labeledwidget::state
+
+ #
+ # Our -width and -height options are slightly different than
+ # those implemented by our base class, so we're going to
+ # remove them and redefine our own.
+ #
+ itk_option remove iwidgets::Scrolledwidget::width
+ itk_option remove iwidgets::Scrolledwidget::height
+
+ #
+ # Create a clipping frame which will provide the border for
+ # relief display.
+ #
+ itk_component add clipper {
+ frame $itk_interior.clipper
+ } {
+ usual
+
+ keep -borderwidth -relief -highlightthickness -highlightcolor
+ rename -highlightbackground -background background Background
+ }
+ grid $itk_component(clipper) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 0 -weight 1
+
+ #
+ # Create a text widget for displaying our hierarchy.
+ #
+ itk_component add list {
+ text $itk_component(clipper).list -wrap none -cursor center_ptr \
+ -state disabled -width 1 -height 1 \
+ -xscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.horizsb] \
+ -yscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.vertsb] \
+ -borderwidth 0 -highlightthickness 0
+ } {
+ usual
+
+ keep -spacing1 -spacing2 -spacing3 -tabs
+ rename -font -textfont textFont Font
+ rename -background -textbackground textBackground Background
+ ignore -highlightthickness -highlightcolor
+ ignore -insertbackground -insertborderwidth
+ ignore -insertontime -insertofftime -insertwidth
+ ignore -selectborderwidth
+ ignore -borderwidth
+ }
+ grid $itk_component(list) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $itk_component(clipper) 0 -weight 1
+ grid columnconfigure $itk_component(clipper) 0 -weight 1
+
+ #
+ # Configure the command on the vertical scroll bar in the base class.
+ #
+ $itk_component(vertsb) configure \
+ -command [itcl::code $itk_component(list) yview]
+
+ #
+ # Configure the command on the horizontal scroll bar in the base class.
+ #
+ $itk_component(horizsb) configure \
+ -command [itcl::code $itk_component(list) xview]
+
+ #
+ # Configure our text component's tab settings for twenty levels.
+ #
+ set tabs ""
+ for {set i 1} {$i < 20} {incr i} {
+ lappend tabs [expr {$i*12+4}]
+ }
+ $itk_component(list) configure -tabs $tabs
+
+ #
+ # Add popup menus that can be configured by the user to add
+ # new functionality.
+ #
+ itk_component add itemMenu {
+ menu $itk_component(list).itemmenu -tearoff 0
+ } {
+ usual
+ ignore -tearoff
+ rename -cursor -menucursor menuCursor Cursor
+ }
+
+ itk_component add bgMenu {
+ menu $itk_component(list).bgmenu -tearoff 0
+ } {
+ usual
+ ignore -tearoff
+ rename -cursor -menucursor menuCursor Cursor
+ }
+
+ #
+ # Adjust the bind tags to remove the class bindings. Also, add
+ # bindings for mouse button 1 to do selection and button 3 to
+ # display a popup.
+ #
+ bindtags $itk_component(list) [list $itk_component(list) . all]
+
+ bind $itk_component(list) <ButtonPress-1> \
+ [itcl::code $this _select %x %y]
+
+ bind $itk_component(list) <Double-1> \
+ [itcl::code $this _double %x %y]
+
+ bind $itk_component(list) <ButtonPress-3> \
+ [itcl::code $this _post %x %y]
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::destructor {} {
+ if {$_pending != ""} {
+ after cancel $_pending
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -font
+#
+# Font used for text in the list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::font {
+ $itk_component(list) tag configure info \
+ -font $itk_option(-font) -spacing1 6
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectbackground
+#
+# Background color scheme for selected nodes.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::selectbackground {
+ $itk_component(list) tag configure hilite \
+ -background $itk_option(-selectbackground)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectforeground
+#
+# Foreground color scheme for selected nodes.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::selectforeground {
+ $itk_component(list) tag configure hilite \
+ -foreground $itk_option(-selectforeground)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -markbackground
+#
+# Background color scheme for marked nodes.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::markbackground {
+ $itk_component(list) tag configure lowlite \
+ -background $itk_option(-markbackground)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -markforeground
+#
+# Foreground color scheme for marked nodes.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::markforeground {
+ $itk_component(list) tag configure lowlite \
+ -foreground $itk_option(-markforeground)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -querycommand
+#
+# Command executed to query the contents of each node. If this
+# command contains "%n", it is replaced with the name of the desired
+# node. In its simpilest form it should return the children of the
+# given node as a list which will be depicted in the display.
+#
+# Since the names of the children are used as tags in the underlying
+# text widget, each child must be unique in the hierarchy. Due to
+# the unique requirement, the nodes shall be reffered to as uids
+# or uid in the singular sense.
+#
+# {uid [uid ...]}
+#
+# where uid is a unique id and primary key for the hierarchy entry
+#
+# Should the unique requirement pose a problem, the list returned
+# can take on another more extended form which enables the
+# association of text to be displayed with the uids. The uid must
+# still be unique, but the text does not have to obey the unique
+# rule. In addition, the format also allows the specification of
+# additional tags to be used on the same entry in the hierarchy
+# as the uid and additional icons to be displayed just before
+# the node. The tags and icons are considered to be the property of
+# the user in that the hierarchy widget will not depend on any of
+# their values.
+#
+# {{uid [text [tags [icons]]]} {uid [text [tags [icons]]]} ...}
+#
+# where uid is a unique id and primary key for the hierarchy entry
+# text is the text to be displayed for this uid
+# tags is a list of user tags to be applied to the entry
+# icons is a list of icons to be displayed in front of the text
+#
+# The hierarchy widget does a look ahead from each node to determine
+# if the node has a children. This can be cost some performace with
+# large hierarchies. User's can avoid this by providing a hint in
+# the user tags. A tag of "leaf" or "branch" tells the hierarchy
+# widget the information it needs to know thereby avoiding the look
+# ahead operation.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::querycommand {
+ clear
+ draw -eventually
+
+ # Added for SF ticket #596111
+ _configureTags
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectcommand
+#
+# Command executed to select an item in the list. If this command
+# contains "%n", it is replaced with the name of the selected node.
+# If it contains a "%s", it is replaced with a boolean indicator of
+# the node's current selection status, where a value of 1 denotes
+# that the node is currently selected and 0 that it is not.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::selectcommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -dblclickcommand
+#
+# Command executed to double click an item in the list. If this command
+# contains "%n", it is replaced with the name of the selected node.
+# If it contains a "%s", it is replaced with a boolean indicator of
+# the node's current selection status, where a value of 1 denotes
+# that the node is currently selected and 0 that it is not.
+#
+# Douglas R. Howard, Jr.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::dblclickcommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -iconcommand
+#
+# Command executed upon selection of user icons. If this command
+# contains "%n", it is replaced with the name of the node the icon
+# belongs to. Should it contain "%i" then the icon name is
+# substituted.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::iconcommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -icondblcommand
+#
+# Command executed upon double selection of user icons. If this command
+# contains "%n", it is replaced with the name of the node the icon
+# belongs to. Should it contain "%i" then the icon name is
+# substituted.
+#
+# Douglas R. Howard, Jr.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::icondblcommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -imagecommand
+#
+# Command executed upon selection of image icons. If this command
+# contains "%n", it is replaced with the name of the node the icon
+# belongs to. Should it contain "%i" then the icon name is
+# substituted.
+#
+# Douglas R. Howard, Jr.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::imagecommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -imagedblcommand
+#
+# Command executed upon double selection of user icons. If this command
+# contains "%n", it is replaced with the name of the node the icon
+# belongs to.
+#
+# Douglas R. Howard, Jr.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::imagedblcommand {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -alwaysquery
+#
+# Boolean flag which tells the hierarchy widget weather or not
+# each refresh of the display should be via a new query using
+# the -querycommand option or use the values previous found the
+# last time the query was made.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::alwaysquery {
+ switch -- $itk_option(-alwaysquery) {
+ 1 - true - yes - on {
+ ;# okay
+ }
+ 0 - false - no - off {
+ ;# okay
+ }
+ default {
+ error "bad alwaysquery option \"$itk_option(-alwaysquery)\":\
+ should be boolean"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -filter
+#
+# When true only the branch nodes and selected items are displayed.
+# This gives a compact view of important items.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::filter {
+ switch -- $itk_option(-filter) {
+ 1 - true - yes - on {
+ set newCode {set display [info exists _selected($child)]}
+ }
+ 0 - false - no - off {
+ set newCode {set display 1}
+ }
+ default {
+ error "bad filter option \"$itk_option(-filter)\":\
+ should be boolean"
+ }
+ }
+ if {$newCode != $_filterCode} {
+ set _filterCode $newCode
+ draw -eventually
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -expanded
+#
+# When true, the hierarchy will be completely expanded when it
+# is first displayed. A fresh display can be triggered by
+# resetting the -querycommand option.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::expanded {
+ switch -- $itk_option(-expanded) {
+ 1 - true - yes - on {
+ ;# okay
+ }
+ 0 - false - no - off {
+ ;# okay
+ }
+ default {
+ error "bad expanded option \"$itk_option(-expanded)\":\
+ should be boolean"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -openicon
+#
+# Specifies the open icon image to be used in the hierarchy. Should
+# one not be provided, then one will be generated, pixmap if
+# possible, bitmap otherwise.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::openicon {
+ if {$itk_option(-openicon) == {}} {
+ if {[lsearch [image names] openFolder] == -1} {
+ if {[lsearch [image types] pixmap] != -1} {
+ image create pixmap openFolder -data {
+ /* XPM */
+ static char * dir_opened [] = {
+ "16 16 4 1",
+ /* colors */
+ ". c grey85 m white g4 grey90",
+ "b c black m black g4 black",
+ "y c yellow m white g4 grey80",
+ "g c grey70 m white g4 grey70",
+ /* pixels */
+ "................",
+ "................",
+ "................",
+ "..bbbb..........",
+ ".bggggb.........",
+ "bggggggbbbbbbb..",
+ "bggggggggggggb..",
+ "bgbbbbbbbbbbbbbb",
+ "bgbyyyyyyyyyyybb",
+ "bbyyyyyyyyyyyyb.",
+ "bbyyyyyyyyyyybb.",
+ "byyyyyyyyyyyyb..",
+ "bbbbbbbbbbbbbb..",
+ "................",
+ "................",
+ "................"};
+ }
+ } else {
+ image create bitmap openFolder -data {
+ #define open_width 16
+ #define open_height 16
+ static char open_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00,
+ 0x81, 0x3f, 0x01, 0x20, 0xf9, 0xff, 0x0d, 0xc0,
+ 0x07, 0x40, 0x03, 0x60, 0x01, 0x20, 0x01, 0x30,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ }
+ }
+ }
+ set itk_option(-openicon) openFolder
+ } else {
+ if {[lsearch [image names] $itk_option(-openicon)] == -1} {
+ error "bad openicon option \"$itk_option(-openicon)\":\
+ should be an existing image"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -closedicon
+#
+# Specifies the closed icon image to be used in the hierarchy.
+# Should one not be provided, then one will be generated, pixmap if
+# possible, bitmap otherwise.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::closedicon {
+ if {$itk_option(-closedicon) == {}} {
+ if {[lsearch [image names] closedFolder] == -1} {
+ if {[lsearch [image types] pixmap] != -1} {
+ image create pixmap closedFolder -data {
+ /* XPM */
+ static char *dir_closed[] = {
+ "16 16 3 1",
+ ". c grey85 m white g4 grey90",
+ "b c black m black g4 black",
+ "y c yellow m white g4 grey80",
+ "................",
+ "................",
+ "................",
+ "..bbbb..........",
+ ".byyyyb.........",
+ "bbbbbbbbbbbbbb..",
+ "byyyyyyyyyyyyb..",
+ "byyyyyyyyyyyyb..",
+ "byyyyyyyyyyyyb..",
+ "byyyyyyyyyyyyb..",
+ "byyyyyyyyyyyyb..",
+ "byyyyyyyyyyyyb..",
+ "bbbbbbbbbbbbbb..",
+ "................",
+ "................",
+ "................"};
+ }
+ } else {
+ image create bitmap closedFolder -data {
+ #define closed_width 16
+ #define closed_height 16
+ static char closed_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x84, 0x00,
+ 0xfe, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40,
+ 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40,
+ 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ }
+ }
+ }
+ set itk_option(-closedicon) closedFolder
+ } else {
+ if {[lsearch [image names] $itk_option(-closedicon)] == -1} {
+ error "bad closedicon option \"$itk_option(-closedicon)\":\
+ should be an existing image"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -nodeicon
+#
+# Specifies the node icon image to be used in the hierarchy. Should
+# one not be provided, then one will be generated, pixmap if
+# possible, bitmap otherwise.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::nodeicon {
+ if {$itk_option(-nodeicon) == {}} {
+ if {[lsearch [image names] nodeFolder] == -1} {
+ if {[lsearch [image types] pixmap] != -1} {
+ image create pixmap nodeFolder -data {
+ /* XPM */
+ static char *dir_node[] = {
+ "16 16 3 1",
+ ". c grey85 m white g4 grey90",
+ "b c black m black g4 black",
+ "y c yellow m white g4 grey80",
+ "................",
+ "................",
+ "................",
+ "...bbbbbbbbbbb..",
+ "..bybyyyyyyyyb..",
+ ".byybyyyyyyyyb..",
+ "byyybyyyyyyyyb..",
+ "bbbbbyyyyyyyyb..",
+ "byyyyyyyyyyyyb..",
+ "byyyyyyyyyyyyb..",
+ "byyyyyyyyyyyyb..",
+ "byyyyyyyyyyyyb..",
+ "bbbbbbbbbbbbbb..",
+ "................",
+ "................",
+ "................"};
+ }
+ } else {
+ image create bitmap nodeFolder -data {
+ #define node_width 16
+ #define node_height 16
+ static char node_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x50, 0x40,
+ 0x48, 0x40, 0x44, 0x40, 0x42, 0x40, 0x7e, 0x40,
+ 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40,
+ 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ }
+ }
+ }
+ set itk_option(-nodeicon) nodeFolder
+ } else {
+ if {[lsearch [image names] $itk_option(-nodeicon)] == -1} {
+ error "bad nodeicon option \"$itk_option(-nodeicon)\":\
+ should be an existing image"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -width
+#
+# Specifies the width of the hierarchy widget as an entire unit.
+# The value may be specified in any of the forms acceptable to
+# Tk_GetPixels. Any additional space needed to display the other
+# components such as labels, margins, and scrollbars force the text
+# to be compressed. A value of zero along with the same value for
+# the height causes the value given for the visibleitems option
+# to be applied which administers geometry constraints in a different
+# manner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::width {
+ if {$itk_option(-width) != 0} {
+ set shell [lindex [grid info $itk_component(clipper)] 1]
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $shell]} {
+ grid propagate $shell no
+ }
+
+ $itk_component(list) configure -width 1
+ $shell configure \
+ -width [winfo pixels $shell $itk_option(-width)]
+ } else {
+ configure -visibleitems $itk_option(-visibleitems)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -height
+#
+# Specifies the height of the hierarchy widget as an entire unit.
+# The value may be specified in any of the forms acceptable to
+# Tk_GetPixels. Any additional space needed to display the other
+# components such as labels, margins, and scrollbars force the text
+# to be compressed. A value of zero along with the same value for
+# the width causes the value given for the visibleitems option
+# to be applied which administers geometry constraints in a different
+# manner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::height {
+ if {$itk_option(-height) != 0} {
+ set shell [lindex [grid info $itk_component(clipper)] 1]
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $shell]} {
+ grid propagate $shell no
+ }
+
+ $itk_component(list) configure -height 1
+ $shell configure \
+ -height [winfo pixels $shell $itk_option(-height)]
+ } else {
+ configure -visibleitems $itk_option(-visibleitems)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -visibleitems
+#
+# Specified the widthxheight in characters and lines for the text.
+# This option is only administered if the width and height options
+# are both set to zero, otherwise they take precedence. With the
+# visibleitems option engaged, geometry constraints are maintained
+# only on the text. The size of the other components such as
+# labels, margins, and scroll bars, are additive and independent,
+# effecting the overall size of the scrolled text. In contrast,
+# should the width and height options have non zero values, they
+# are applied to the scrolled text as a whole. The text is
+# compressed or expanded to maintain the geometry constraints.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::visibleitems {
+ if {[regexp {^[0-9]+x[0-9]+$} $itk_option(-visibleitems)]} {
+ if {($itk_option(-width) == 0) && \
+ ($itk_option(-height) == 0)} {
+ set chars [lindex [split $itk_option(-visibleitems) x] 0]
+ set lines [lindex [split $itk_option(-visibleitems) x] 1]
+
+ set shell [lindex [grid info $itk_component(clipper)] 1]
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {! [grid propagate $shell]} {
+ grid propagate $shell yes
+ }
+
+ $itk_component(list) configure -width $chars -height $lines
+ }
+
+ } else {
+ error "bad visibleitems option\
+ \"$itk_option(-visibleitems)\": should be\
+ widthxheight"
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -textmenuloadcommand
+#
+# Dynamically loads the popup menu based on what was selected.
+#
+# Douglas R. Howard, Jr.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::textmenuloadcommand {}
+
+# ------------------------------------------------------------------
+# OPTION: -imagemenuloadcommand
+#
+# Dynamically loads the popup menu based on what was selected.
+#
+# Douglas R. Howard, Jr.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hierarchy::imagemenuloadcommand {}
+
+
+# ------------------------------------------------------------------
+# PUBLIC METHODS
+# ------------------------------------------------------------------
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: clear
+#
+# Removes all items from the display including all tags and icons.
+# The display will remain empty until the -filter or -querycommand
+# options are set.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::clear {} {
+ $itk_component(list) configure -state normal -cursor watch
+ $itk_component(list) delete 1.0 end
+ $itk_component(list) configure -state disabled -cursor $itk_option(-cursor)
+
+ # Clear the tags
+ eval $itk_component(list) tag delete [$itk_component(list) tag names]
+
+ catch {unset _nodes}
+ catch {unset _text}
+ catch {unset _tags}
+ catch {unset _icons}
+ catch {unset _states}
+ catch {unset _images}
+ catch {unset _indents}
+ catch {unset _marked}
+ catch {unset _selected}
+ set _markers ""
+ set _posted ""
+ set _ucounter 0
+ set _hcounter 0
+
+ foreach mark [$itk_component(list) mark names] {
+ $itk_component(list) mark unset $mark
+ }
+
+ return
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: selection option ?uid uid...?
+#
+# Handles all operations controlling selections in the hierarchy.
+# Selections may be cleared, added, removed, or queried. The add and
+# remove options accept a series of unique ids.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::selection {op args} {
+ switch -- $op {
+ clear {
+ $itk_component(list) tag remove hilite 1.0 end
+ catch {unset _selected}
+ return
+ }
+ add {
+ foreach node $args {
+ set _selected($node) 1
+ catch {
+ $itk_component(list) tag add hilite \
+ "$node.first" "$node.last"
+ }
+ }
+ }
+ remove {
+ foreach node $args {
+ catch {
+ unset _selected($node)
+ $itk_component(list) tag remove hilite \
+ "$node.first" "$node.last"
+ }
+ }
+ }
+ get {
+ return [array names _selected]
+ }
+ default {
+ error "bad selection operation \"$op\":\
+ should be add, remove, clear or get"
+ }
+ }
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: mark option ?arg arg...?
+#
+# Handles all operations controlling marks in the hierarchy. Marks may
+# be cleared, added, removed, or queried. The add and remove options
+# accept a series of unique ids.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::mark {op args} {
+ switch -- $op {
+ clear {
+ $itk_component(list) tag remove lowlite 1.0 end
+ catch {unset _marked}
+ return
+ }
+ add {
+ foreach node $args {
+ set _marked($node) 1
+ catch {
+ $itk_component(list) tag add lowlite \
+ "$node.first" "$node.last"
+ }
+ }
+ }
+ remove {
+ foreach node $args {
+ catch {
+ unset _marked($node)
+ $itk_component(list) tag remove lowlite \
+ "$node.first" "$node.last"
+ }
+ }
+ }
+ get {
+ return [array names _marked]
+ }
+ default {
+ error "bad mark operation \"$op\":\
+ should be add, remove, clear or get"
+ }
+ }
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: current
+#
+# Returns the node that was most recently selected by the right mouse
+# button when the item menu was posted. Usually used by the code
+# in the item menu to figure out what item is being manipulated.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::current {} {
+ return $_posted
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: expand node
+#
+# Expands the hierarchy beneath the specified node. Since this can take
+# a moment for large hierarchies, the cursor will be changed to a watch
+# during the expansion.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::expand {node} {
+ if {! [info exists _states($node)]} {
+ error "bad expand node argument: \"$node\", the node doesn't exist"
+ }
+
+ if {!$_states($node) && \
+ (([lsearch $_tags($node) branch] != -1) || \
+ ([llength [_contents $node]] > 0))} {
+ $itk_component(list) configure -state normal -cursor watch
+ update
+
+ #
+ # Get the indentation level for the node.
+ #
+ set indent $_indents($node)
+
+ set _markers ""
+ $itk_component(list) mark set insert "$node:start"
+ _drawLevel $node $indent
+
+ #
+ # Following the draw, all our markers need adjusting.
+ #
+ foreach {name index} $_markers {
+ $itk_component(list) mark set $name $index
+ }
+
+ #
+ # Set the image to be the open icon, denote the new state,
+ # and set the cursor back to normal along with the state.
+ #
+ $_images($node) configure -image $itk_option(-openicon)
+
+ set _states($node) 1
+
+ $itk_component(list) configure -state disabled \
+ -cursor $itk_option(-cursor)
+ }
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: collapse node
+#
+# Collapses the hierarchy beneath the specified node. Since this can
+# take a moment for large hierarchies, the cursor will be changed to a
+# watch during the expansion.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::collapse {node} {
+ if {! [info exists _states($node)]} {
+ error "bad collapse node argument: \"$node\", the node doesn't exist"
+ }
+
+ if {[info exists _states($node)] && $_states($node) && \
+ (([lsearch $_tags($node) branch] != -1) || \
+ ([llength [_contents $node]] > 0))} {
+ $itk_component(list) configure -state normal -cursor watch
+ update
+
+ _deselectSubNodes $node
+
+ $itk_component(list) delete "$node:start" "$node:end"
+
+ catch {$_images($node) configure -image $itk_option(-closedicon)}
+
+ set _states($node) 0
+
+ $itk_component(list) configure -state disabled \
+ -cursor $itk_option(-cursor)
+ }
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: toggle node
+#
+# Toggles the hierarchy beneath the specified node. If the hierarchy
+# is currently expanded, then it is collapsed, and vice-versa.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::toggle {node} {
+ if {! [info exists _states($node)]} {
+ error "bad toggle node argument: \"$node\", the node doesn't exist"
+ }
+
+ if {$_states($node)} {
+ collapse $node
+ } else {
+ expand $node
+ }
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: prune node
+#
+# Removes a particular node from the hierarchy.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::prune {node} {
+ #
+ # While we're working, change the state and cursor so we can
+ # edit the text and give a busy visual clue.
+ #
+ $itk_component(list) configure -state normal -cursor watch
+
+ #
+ # Recursively delete all the subnode information from our internal
+ # arrays and remove all the tags.
+ #
+ _deleteNodeInfo $node
+
+ #
+ # If the mark $node:end exists then the node has decendents so
+ # so we'll remove from the mark $node:start to $node:end in order
+ # to delete all the subnodes below it in the text.
+ #
+ if {[lsearch [$itk_component(list) mark names] $node:end] != -1} {
+ $itk_component(list) delete $node:start $node:end
+ $itk_component(list) mark unset $node:end
+ }
+
+ #
+ # Next we need to remove the node itself. Using the ranges for
+ # its tag we'll remove it from line start to the end plus one
+ # character which takes us to the start of the next node.
+ #
+ foreach {start end} [$itk_component(list) tag ranges $node] {
+ $itk_component(list) delete "$start linestart" "$end + 1 char"
+ }
+
+ #
+ # Delete the tag for this node.
+ #
+ $itk_component(list) tag delete $node
+
+ #
+ # The node must be removed from the list of subnodes for its parent.
+ # We don't really have a clean way to do upwards referencing, so
+ # the dirty way will have to do. We'll cycle through each node
+ # and if this node is in its list of subnodes, we'll remove it.
+ #
+ foreach uid [array names _nodes] {
+ if {[set index [lsearch $_nodes($uid) $node]] != -1} {
+ set _nodes($uid) [lreplace $_nodes($uid) $index $index]
+ }
+ }
+
+ #
+ # We're done, so change the state and cursor back to their
+ # original values.
+ #
+ $itk_component(list) configure -state disabled -cursor $itk_option(-cursor)
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: draw ?when?
+#
+# Performs a complete draw of the entire hierarchy.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::draw {{when -now}} {
+ if {$when == "-eventually"} {
+ if {$_pending == ""} {
+ set _pending [after idle [itcl::code $this draw -now]]
+ }
+ return
+ } elseif {$when != "-now"} {
+ error "bad when option \"$when\": should be -eventually or -now"
+ }
+ $itk_component(list) configure -state normal -cursor watch
+ update
+
+ $itk_component(list) delete 1.0 end
+ catch {unset _images}
+ set _markers ""
+
+ _drawLevel "" ""
+
+ foreach {name index} $_markers {
+ $itk_component(list) mark set $name $index
+ }
+
+ $itk_component(list) configure -state disabled -cursor $itk_option(-cursor)
+ set _pending ""
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: refresh node
+#
+# Performs a redraw of a specific node. If that node is currently
+# not visible, then no action is taken.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::refresh {node} {
+ if {! [info exists _nodes($node)]} {
+ error "bad refresh node argument: \"$node\", the node doesn't exist"
+ }
+
+
+ if {! $_states($node)} {return}
+
+ foreach parent [_getHeritage $node] {
+ if {! $_states($parent)} {return}
+ }
+
+ $itk_component(list) configure -state normal -cursor watch
+ $itk_component(list) delete $node:start $node:end
+
+ set _markers ""
+ $itk_component(list) mark set insert "$node:start"
+ set indent $_indents($node)
+
+ _drawLevel $node $indent
+
+ foreach {name index} $_markers {
+ $itk_component(list) mark set $name $index
+ }
+
+ $itk_component(list) configure -state disabled -cursor $itk_option(-cursor)
+}
+
+# ------------------------------------------------------------------
+# THIN WRAPPED TEXT METHODS:
+#
+# The following methods are thin wraps of standard text methods.
+# Consult the Tk text man pages for functionallity and argument
+# documentation.
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: bbox index
+#
+# Returns four element list describing the bounding box for the list
+# item at index
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::bbox {index} {
+ return [$itk_component(list) bbox $index]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD compare index1 op index2
+#
+# Compare indices according to relational operator.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::compare {index1 op index2} {
+ return [$itk_component(list) compare $index1 $op $index2]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD delete first ?last?
+#
+# Delete a range of characters from the text.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::delete {first {last {}}} {
+ $itk_component(list) configure -state normal -cursor watch
+ $itk_component(list) delete $first $last
+ $itk_component(list) configure -state disabled -cursor $itk_option(-cursor)
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD dump ?switches? index1 ?index2?
+#
+# Returns information about the contents of the text widget from
+# index1 to index2.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::dump {args} {
+ return [eval $itk_component(list) dump $args]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD dlineinfo index
+#
+# Returns a five element list describing the area occupied by the
+# display line containing index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::dlineinfo {index} {
+ return [$itk_component(list) dlineinfo $index]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD get index1 ?index2?
+#
+# Return text from start index to end index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::get {index1 {index2 {}}} {
+ return [$itk_component(list) get $index1 $index2]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD index index
+#
+# Return position corresponding to index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::index {index} {
+ return [$itk_component(list) index $index]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD insert index chars ?tagList?
+#
+# Insert text at index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::insert {args} {
+ $itk_component(list) configure -state normal -cursor watch
+ eval $itk_component(list) insert $args
+ $itk_component(list) configure -state disabled -cursor $itk_option(-cursor)
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD scan option args
+#
+# Implements scanning on texts.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::scan {option args} {
+ eval $itk_component(list) scan $option $args
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD search ?switches? pattern index ?varName?
+#
+# Searches the text for characters matching a pattern.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::search {args} {
+ return [eval $itk_component(list) search $args]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD see index
+#
+# Adjusts the view in the window so the character at index is
+# visible.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::see {index} {
+ $itk_component(list) see $index
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD tag option ?arg arg ...?
+#
+# Manipulate tags dependent on options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::tag {op args} {
+ return [eval $itk_component(list) tag $op $args]
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD window option ?arg arg ...?
+#
+# Manipulate embedded windows.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::window {option args} {
+ return [eval $itk_component(list) window $option $args]
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: xview args
+#
+# Thin wrap of the text widget's xview command.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::xview {args} {
+ return [eval itk_component(list) xview $args]
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: yview args
+#
+# Thin wrap of the text widget's yview command.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::yview {args} {
+ return [eval $itk_component(list) yview $args]
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: expanded node
+#
+# Tells if a node is expanded or collapsed
+#
+# Douglas R. Howard, Jr.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::expanded {node} {
+ if {! [info exists _states($node)]} {
+ error "bad collapse node argument: \"$node\", the node doesn't exist"
+ }
+
+ return $_states($node)
+}
+
+# ----------------------------------------------------------------------
+# PUBLIC METHOD: expState
+#
+# Returns a list of all expanded nodes
+#
+# Douglas R. Howard, Jr.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::expState {} {
+ set nodes [_contents ""]
+ set open ""
+ set i 0
+ while {1} {
+ if {[info exists _states([lindex $nodes $i])] &&
+ $_states([lindex $nodes $i])} {
+ lappend open [lindex $nodes $i]
+ foreach child [_contents [lindex $nodes $i]] {
+ lappend nodes $child
+ }
+ }
+ incr i
+ if {$i >= [llength $nodes]} {break}
+ }
+
+ return $open
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHODS
+# ------------------------------------------------------------------
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _drawLevel node indent
+#
+# Used internally by draw to draw one level of the hierarchy.
+# Draws all of the nodes under node, using the indent string to
+# indent nodes.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_drawLevel {node indent} {
+ lappend _markers "$node:start" [$itk_component(list) index insert]
+ set bg [$itk_component(list) cget -background]
+
+ #
+ # Obtain the list of subnodes for this node and cycle through
+ # each one displaying it in the hierarchy.
+ #
+ foreach child [_contents $node] {
+ set _images($child) "$itk_component(list).hicon[incr _hcounter]"
+
+ if {![info exists _states($child)]} {
+ set _states($child) $itk_option(-expanded)
+ }
+
+ #
+ # Check the user tags to see if they have been kind enough
+ # to tell us ahead of time what type of node we are dealing
+ # with branch or leaf. If they neglected to do so, then
+ # get the contents of the child node to see if it has children
+ # itself.
+ #
+ set display 0
+
+ if {[lsearch $_tags($child) leaf] != -1} {
+ set type leaf
+ } elseif {[lsearch $_tags($child) branch] != -1} {
+ set type branch
+ } else {
+ if {[llength [_contents $child]] == 0} {
+ set type leaf
+ } else {
+ set type branch
+ }
+ }
+
+ #
+ # Now that we know the type of node, branch or leaf, we know
+ # the type of icon to use.
+ #
+ if {$type == "leaf"} {
+ set icon $itk_option(-nodeicon)
+ eval $_filterCode
+ } else {
+ if {$_states($child)} {
+ set icon $itk_option(-openicon)
+ } else {
+ set icon $itk_option(-closedicon)
+ }
+ set display 1
+ }
+
+ #
+ # If display is set then we're going to be drawing this node.
+ # Save off the indentation level for this node and do the indent.
+ #
+ if {$display} {
+ set _indents($child) "$indent\t"
+ $itk_component(list) insert insert $indent
+
+ #
+ # Add the branch or leaf icon and setup a binding to toggle
+ # its expanded/collapsed state.
+ #
+ label $_images($child) -image $icon -background $bg
+ # DRH - enhanced and added features that handle image clicking,
+ # double clicking, and right clicking behavior
+ bind $_images($child) <ButtonPress-1> \
+ "[itcl::code $this toggle $child]; [itcl::code $this _imageSelect $child]"
+ bind $_images($child) <Double-1> [itcl::code $this _imageDblClick $child]
+ bind $_images($child) <ButtonPress-3> \
+ [itcl::code $this _imagePost $child $_images($child) $type %x %y]
+ $itk_component(list) window create insert -window $_images($child)
+
+ #
+ # If any user icons exist then draw them as well. The little
+ # regexp is just to check and see if they've passed in a
+ # command which needs to be evaluated as opposed to just
+ # a variable. Also, attach a binding to call them if their
+ # icon is selected.
+ #
+ if {[info exists _icons($child)]} {
+ foreach image $_icons($child) {
+ set wid "$itk_component(list).uicon[incr _ucounter]"
+
+ if {[regexp {\[.*\]} $image]} {
+ eval label $wid -image $image -background $bg
+ } else {
+ label $wid -image $image -background $bg
+ }
+
+ # DRH - this will bind events to the icons to allow
+ # clicking, double clicking, and right clicking actions.
+ bind $wid <ButtonPress-1> \
+ [itcl::code $this _iconSelect $child $image]
+ bind $wid <Double-1> \
+ [itcl::code $this _iconDblSelect $child $image]
+ bind $wid <ButtonPress-3> \
+ [itcl::code $this _imagePost $child $wid $type %x %y]
+ $itk_component(list) window create insert -window $wid
+ }
+ }
+
+ #
+ # Create the list of tags to be applied to the text. Start
+ # out with a tag of "info" and append "hilite" if the node
+ # is currently selected, finally add the tags given by the
+ # user.
+ #
+ set texttags [list "info" $child]
+
+ if {[info exists _selected($child)]} {
+ lappend texttags hilite
+ }
+
+ # The following conditional added for SF ticket #600941.
+ if {[info exists _marked($child)]} {
+ lappend texttags lowlite
+ }
+
+ foreach tag $_tags($child) {
+ lappend texttags $tag
+ }
+
+ #
+ # Insert the text for the node along with the tags and
+ # append to the markers the start of this node. The text
+ # has been broken at newlines into a list. We'll make sure
+ # that each line is at the same indentation position.
+ #
+ set firstline 1
+ foreach line $_text($child) {
+ if {$firstline} {
+ $itk_component(list) insert insert " "
+ } else {
+ $itk_component(list) insert insert "$indent\t"
+ }
+
+ $itk_component(list) insert insert $line $texttags "\n"
+ set firstline 0
+ }
+
+ $itk_component(list) tag raise $child
+ lappend _markers "$child:start" [$itk_component(list) index insert]
+
+ #
+ # If the state of the node is open, proceed to draw the next
+ # node below it in the hierarchy.
+ #
+ if {$_states($child)} {
+ _drawLevel $child "$indent\t"
+ }
+ }
+ }
+
+ lappend _markers "$node:end" [$itk_component(list) index insert]
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _contents uid
+#
+# Used internally to get the contents of a particular node. If this
+# is the first time the node has been seen or the -alwaysquery
+# option is set, the -querycommand code is executed to query the node
+# list, and the list is stored until the next time it is needed.
+#
+# The querycommand may return not only the list of subnodes for the
+# node but additional information on the tags and icons to be used.
+# The return value must be parsed based on the number of elements in
+# the list where the format is a list of lists:
+#
+# {{uid [text [tags [icons]]]} {uid [text [tags [icons]]]} ...}
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_contents {uid} {
+ if {$itk_option(-alwaysquery)} {
+ } else {
+ if {[info exists _nodes($uid)]} {
+ return $_nodes($uid)
+ }
+ }
+
+ #
+ # Substitute any %n's for the node name whose children we're
+ # interested in obtaining.
+ #
+ set cmd $itk_option(-querycommand)
+ regsub -all {%n} $cmd [list $uid] cmd
+
+ set nodeinfolist [uplevel \#0 $cmd]
+
+ #
+ # Cycle through the node information returned by the query
+ # command determining if additional information such as text,
+ # user tags, or user icons have been provided. For text,
+ # break it into a list at any newline characters.
+ #
+ set _nodes($uid) {}
+
+ foreach nodeinfo $nodeinfolist {
+ set subnodeuid [lindex $nodeinfo 0]
+ lappend _nodes($uid) $subnodeuid
+
+ set llen [llength $nodeinfo]
+
+ if {$llen == 0 || $llen > 4} {
+ error "invalid number of elements returned by query\
+ command for node: \"$uid\",\
+ should be uid \[text \[tags \[icons\]\]\]"
+ }
+
+ if {$llen == 1} {
+ set _text($subnodeuid) [split $subnodeuid \n]
+ }
+ if {$llen > 1} {
+ set _text($subnodeuid) [split [lindex $nodeinfo 1] \n]
+ }
+ if {$llen > 2} {
+ set _tags($subnodeuid) [lindex $nodeinfo 2]
+ } else {
+ set _tags($subnodeuid) unknown
+ }
+ if {$llen > 3} {
+ set _icons($subnodeuid) [lindex $nodeinfo 3]
+ }
+ }
+
+ #
+ # Return the list of nodes.
+ #
+ return $_nodes($uid)
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _post x y
+#
+# Used internally to post the popup menu at the coordinate (x,y)
+# relative to the widget. If (x,y) is on an item, then the itemMenu
+# component is posted. Otherwise, the bgMenu is posted.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_post {x y} {
+ set rx [expr {[winfo rootx $itk_component(list)]+$x}]
+ set ry [expr {[winfo rooty $itk_component(list)]+$y}]
+
+ set index [$itk_component(list) index @$x,$y]
+
+ #
+ # The posted variable will hold the list of tags which exist at
+ # this x,y position that will be passed back to the user. They
+ # don't need to know about our internal tags, info, hilite, and
+ # lowlite, so remove them from the list.
+ #
+ set _posted {}
+
+ foreach tag [$itk_component(list) tag names $index] {
+ if {![_isInternalTag $tag]} {
+ lappend _posted $tag
+ }
+ }
+
+ #
+ # If we have tags then do the popup at this position.
+ #
+ if {$_posted != {}} {
+ # DRH - here is where the user's function for dynamic popup
+ # menu loading is done, if the user has specified to do so with the
+ # "-textmenuloadcommand"
+ if {$itk_option(-textmenuloadcommand) != {}} {
+ eval $itk_option(-textmenuloadcommand)
+ }
+ tk_popup $itk_component(itemMenu) $rx $ry
+ } else {
+ tk_popup $itk_component(bgMenu) $rx $ry
+ }
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _imagePost node image type x y
+#
+# Used internally to post the popup menu at the coordinate (x,y)
+# relative to the widget. If (x,y) is on an image, then the itemMenu
+# component is posted.
+#
+# Douglas R. Howard, Jr.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_imagePost {node image type x y} {
+ set rx [expr {[winfo rootx $image]+$x}]
+ set ry [expr {[winfo rooty $image]+$y}]
+
+ #
+ # The posted variable will hold the list of tags which exist at
+ # this x,y position that will be passed back to the user. They
+ # don't need to know about our internal tags, info, hilite, and
+ # lowlite, so remove them from the list.
+ #
+ set _posted {}
+
+ lappend _posted $node $type
+
+ #
+ # If we have tags then do the popup at this position.
+ #
+ if {$itk_option(-imagemenuloadcommand) != {}} {
+ eval $itk_option(-imagemenuloadcommand)
+ }
+ tk_popup $itk_component(itemMenu) $rx $ry
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _select x y
+#
+# Used internally to select an item at the coordinate (x,y) relative
+# to the widget. The command associated with the -selectcommand
+# option is execute following % character substitutions. If %n
+# appears in the command, the selected node is substituted. If %s
+# appears, a boolean value representing the current selection state
+# will be substituted.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_select {x y} {
+ if {$itk_option(-selectcommand) != {}} {
+ if {[set seltags [$itk_component(list) tag names @$x,$y]] != {}} {
+ foreach tag $seltags {
+ if {![_isInternalTag $tag]} {
+ lappend node $tag
+ }
+ }
+
+ if {[lsearch $seltags "hilite"] == -1} {
+ set selectstatus 0
+ } else {
+ set selectstatus 1
+ }
+
+ set cmd $itk_option(-selectcommand)
+ regsub -all {%n} $cmd [lindex $node end] cmd
+ regsub -all {%s} $cmd [list $selectstatus] cmd
+
+ uplevel #0 $cmd
+ }
+ }
+
+ return
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _double x y
+#
+# Used internally to double click an item at the coordinate (x,y) relative
+# to the widget. The command associated with the -dblclickcommand
+# option is execute following % character substitutions. If %n
+# appears in the command, the selected node is substituted. If %s
+# appears, a boolean value representing the current selection state
+# will be substituted.
+#
+# Douglas R. Howard, Jr.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_double {x y} {
+ if {$itk_option(-dblclickcommand) != {}} {
+ if {[set seltags [$itk_component(list) tag names @$x,$y]] != {}} {
+ foreach tag $seltags {
+ if {![_isInternalTag $tag]} {
+ lappend node $tag
+ }
+ }
+
+ if {[lsearch $seltags "hilite"] == -1} {
+ set selectstatus 0
+ } else {
+ set selectstatus 1
+ }
+
+ set cmd $itk_option(-dblclickcommand)
+ regsub -all {%n} $cmd [list $node] cmd
+ regsub -all {%s} $cmd [list $selectstatus] cmd
+
+ uplevel #0 $cmd
+ }
+ }
+
+ return
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _iconSelect node icon
+#
+# Used internally to upon selection of user icons. The -iconcommand
+# is executed after substitution of the node for %n and icon for %i.
+#
+# Douglas R. Howard, Jr.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_iconSelect {node icon} {
+ set cmd $itk_option(-iconcommand)
+ regsub -all {%n} $cmd [list $node] cmd
+ regsub -all {%i} $cmd [list $icon] cmd
+
+ uplevel \#0 $cmd
+
+ return {}
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _iconDblSelect node icon
+#
+# Used internally to upon double selection of user icons. The
+# -icondblcommand is executed after substitution of the node for %n and
+# icon for %i.
+#
+# Douglas R. Howard, Jr.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_iconDblSelect {node icon} {
+ if {$itk_option(-icondblcommand) != {}} {
+ set cmd $itk_option(-icondblcommand)
+ regsub -all {%n} $cmd [list $node] cmd
+ regsub -all {%i} $cmd [list $icon] cmd
+
+ uplevel \#0 $cmd
+ }
+ return {}
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _imageSelect node icon
+#
+# Used internally to upon selection of user icons. The -imagecommand
+# is executed after substitution of the node for %n.
+#
+# Douglas R. Howard, Jr.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_imageSelect {node} {
+ if {$itk_option(-imagecommand) != {}} {
+ set cmd $itk_option(-imagecommand)
+ regsub -all {%n} $cmd [list $node] cmd
+
+ uplevel \#0 $cmd
+ }
+ return {}
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _imageDblClick node
+#
+# Used internally to upon double selection of images. The
+# -imagedblcommand is executed.
+#
+# Douglas R. Howard, Jr.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_imageDblClick {node} {
+ if {$itk_option(-imagedblcommand) != {}} {
+ set cmd $itk_option(-imagedblcommand)
+ regsub -all {%n} $cmd [list $node] cmd
+
+ uplevel \#0 $cmd
+ }
+ return {}
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _deselectSubNodes uid
+#
+# Used internally to recursively deselect all the nodes beneath a
+# particular node.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_deselectSubNodes {uid} {
+ foreach node $_nodes($uid) {
+ if {[array names _selected $node] != {}} {
+ unset _selected($node)
+ }
+
+ if {[array names _nodes $node] != {}} {
+ _deselectSubNodes $node
+ }
+ }
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _deleteNodeInfo uid
+#
+# Used internally to recursively delete all the information about a
+# node and its decendents.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_deleteNodeInfo {uid} {
+ #
+ # Recursively call ourseleves as we go down the hierarchy beneath
+ # this node.
+ #
+ if {[info exists _nodes($uid)]} {
+ foreach node $_nodes($uid) {
+ if {[array names _nodes $node] != {}} {
+ _deleteNodeInfo $node
+ }
+ }
+ }
+
+ #
+ # Unset any entries in our arrays for the node.
+ #
+ catch {unset _nodes($uid)}
+ catch {unset _text($uid)}
+ catch {unset _tags($uid)}
+ catch {unset _icons($uid)}
+ catch {unset _states($uid)}
+ catch {unset _images($uid)}
+ catch {unset _indents($uid)}
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _getParent uid
+#
+# Used internally to determine the parent for a node.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_getParent {uid} {
+ foreach node [array names _nodes] {
+ if {[set index [lsearch $_nodes($node) $uid]] != -1} {
+ return $node
+ }
+ }
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _getHeritage uid
+#
+# Used internally to determine the list of parents for a node.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_getHeritage {uid} {
+ set parents {}
+
+ if {[set parent [_getParent $uid]] != {}} {
+ lappend parents $parent
+ }
+
+ return $parents
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD (could be proc?): _isInternalTag tag
+#
+# Used internally to tags not to used for user callback commands
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_isInternalTag {tag} {
+ set ii [expr {[lsearch -exact {info hilite lowlite unknown} $tag] != -1}];
+ return $ii;
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _configureTags
+#
+# This method added to fix SF ticket #596111. When the -querycommand
+# is reset after initial construction, the text component loses its
+# tag configuration. This method resets the hilite, lowlite, and info
+# tags. csmith: 9/5/02
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Hierarchy::_configureTags {} {
+ tag configure hilite -background $itk_option(-selectbackground) \
+ -foreground $itk_option(-selectforeground)
+ tag configure lowlite -background $itk_option(-markbackground) \
+ -foreground $itk_option(-markforeground)
+ tag configure info -font $itk_option(-font) -spacing1 6
+}
diff --git a/iwidgets/generic/hyperhelp.itk b/iwidgets/generic/hyperhelp.itk
new file mode 100644
index 00000000000..df2ea5e8847
--- /dev/null
+++ b/iwidgets/generic/hyperhelp.itk
@@ -0,0 +1,508 @@
+#
+# Hyperhelp
+# ----------------------------------------------------------------------
+# Implements a help facility using html formatted hypertext files.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Kris Raney EMAIL: kraney@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1996 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.
+# ======================================================================
+
+#
+# Acknowledgements:
+#
+# Special thanks go to Sam Shen(SLShen@lbl.gov), as this code is based on his
+# help.tcl code from tk inspect.
+
+#
+# Default resources.
+#
+option add *Hyperhelp.width 575 widgetDefault
+option add *Hyperhelp.height 450 widgetDefault
+option add *Hyperhelp.modality none widgetDefault
+option add *Hyperhelp.vscrollMode static widgetDefault
+option add *Hyperhelp.hscrollMode static widgetDefault
+option add *Hyperhelp.maxHistory 20 widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Hyperhelp {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -foreground -highlightcolor -highlightthickness \
+ -selectbackground -selectborderwidth -selectforeground \
+ -textbackground
+}
+
+# ------------------------------------------------------------------
+# HYPERHELP
+# ------------------------------------------------------------------
+itcl::class iwidgets::Hyperhelp {
+ inherit iwidgets::Shell
+
+ constructor {args} {}
+
+ itk_option define -topics topics Topics {}
+ itk_option define -helpdir helpdir Directory .
+ itk_option define -title title Title "Help"
+ itk_option define -closecmd closeCmd CloseCmd {}
+ itk_option define -maxhistory maxHistory MaxHistory 20
+
+ public variable beforelink {}
+ public variable afterlink {}
+
+ public method showtopic {topic}
+ public method followlink {link}
+ public method forward {}
+ public method back {}
+ public method updatefeedback {n}
+
+ protected method _readtopic {file {anchorpoint {}}}
+ protected method _pageforward {}
+ protected method _pageback {}
+ protected method _lineforward {}
+ protected method _lineback {}
+ protected method _fill_go_menu {}
+
+ protected variable _history {} ;# History list of viewed pages
+ protected variable _history_ndx -1 ;# current position in history list
+ protected variable _history_len 0 ;# length of history list
+ protected variable _histdir -1 ;# direction in history we just came
+ ;# from
+ protected variable _len 0 ;# length of text to be rendered
+ protected variable _file {} ;# current topic
+
+ private variable _remaining 0 ;# remaining text to be rendered
+ private variable _rendering 0 ;# flag - in process of rendering
+}
+
+#
+# Provide a lowercased access method for the Scrolledlistbox class.
+#
+proc ::iwidgets::hyperhelp {pathName args} {
+ uplevel ::iwidgets::Hyperhelp $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::constructor {args} {
+ itk_option remove iwidgets::Shell::padx iwidgets::Shell::pady
+
+ #
+ # Create a pulldown menu
+ #
+ itk_component add -private menubar {
+ frame $itk_interior.menu -relief raised -bd 2
+ } {
+ keep -background -cursor
+ }
+ pack $itk_component(menubar) -side top -fill x
+
+ itk_component add -private topicmb {
+ menubutton $itk_component(menubar).topicmb -text "Topics" \
+ -menu $itk_component(menubar).topicmb.topicmenu \
+ -underline 0 -padx 8 -pady 2
+ } {
+ keep -background -cursor -font -foreground \
+ -activebackground -activeforeground
+ }
+ pack $itk_component(topicmb) -side left
+
+ itk_component add -private topicmenu {
+ menu $itk_component(topicmb).topicmenu -tearoff no
+ } {
+ keep -background -cursor -font -foreground \
+ -activebackground -activeforeground
+ }
+
+ itk_component add -private navmb {
+ menubutton $itk_component(menubar).navmb -text "Navigate" \
+ -menu $itk_component(menubar).navmb.navmenu \
+ -underline 0 -padx 8 -pady 2
+ } {
+ keep -background -cursor -font -foreground \
+ -activebackground -activeforeground
+ }
+ pack $itk_component(navmb) -side left
+
+ itk_component add -private navmenu {
+ menu $itk_component(navmb).navmenu -tearoff no
+ } {
+ keep -background -cursor -font -foreground \
+ -activebackground -activeforeground
+ }
+ set m $itk_component(navmenu)
+ $m add command -label "Forward" -underline 0 -state disabled \
+ -command [itcl::code $this forward] -accelerator f
+ $m add command -label "Back" -underline 0 -state disabled \
+ -command [itcl::code $this back] -accelerator b
+ $m add cascade -label "Go" -underline 0 -menu $m.go
+
+ itk_component add -private navgo {
+ menu $itk_component(navmenu).go -postcommand [itcl::code $this _fill_go_menu]
+ } {
+ keep -background -cursor -font -foreground \
+ -activebackground -activeforeground
+ }
+
+ #
+ # Create a scrolledhtml object to display help pages
+ #
+ itk_component add scrtxt {
+ iwidgets::scrolledhtml $itk_interior.scrtxt \
+ -linkcommand "$this followlink" -feedback "$this updatefeedback"
+ } {
+ keep -hscrollmode -vscrollmode -background -textbackground \
+ -fontname -fontsize -fixedfont -link \
+ -linkhighlight -borderwidth -cursor -sbwidth -scrollmargin \
+ -width -height -foreground -highlightcolor -visibleitems \
+ -highlightthickness -padx -pady -activerelief \
+ -relief -selectbackground -selectborderwidth \
+ -selectforeground -setgrid -wrap -unknownimage
+ }
+ pack $itk_component(scrtxt) -fill both -expand yes
+
+ #
+ # Bind shortcut keys
+ #
+ bind $itk_component(hull) <Key-f> [itcl::code $this forward]
+ bind $itk_component(hull) <Key-b> [itcl::code $this back]
+ bind $itk_component(hull) <Alt-Right> [itcl::code $this forward]
+ bind $itk_component(hull) <Alt-Left> [itcl::code $this back]
+ bind $itk_component(hull) <Key-space> [itcl::code $this _pageforward]
+ bind $itk_component(hull) <Key-Next> [itcl::code $this _pageforward]
+ bind $itk_component(hull) <Key-BackSpace> [itcl::code $this _pageback]
+ bind $itk_component(hull) <Key-Prior> [itcl::code $this _pageback]
+ bind $itk_component(hull) <Key-Delete> [itcl::code $this _pageback]
+ bind $itk_component(hull) <Key-Down> [itcl::code $this _lineforward]
+ bind $itk_component(hull) <Key-Up> [itcl::code $this _lineback]
+
+ wm title $itk_component(hull) "Help"
+
+ eval itk_initialize $args
+ if {[lsearch -exact $args -closecmd] == -1} {
+ configure -closecmd [itcl::code $this deactivate]
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -topics
+#
+# Specifies the topics to display on the menu. For each topic, there should
+# be a file named <helpdir>/<topic>.html
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hyperhelp::topics {
+ set m $itk_component(topicmenu)
+ $m delete 0 last
+ foreach topic $itk_option(-topics) {
+ if {[lindex $topic 1] == {} } {
+ $m add radiobutton -variable topic \
+ -value $topic \
+ -label $topic \
+ -command [list $this showtopic $topic]
+ } else {
+ if {[string index [file dirname [lindex $topic 1]] 0] != "/" && \
+ [string index [file dirname [lindex $topic 1]] 0] != "~"} {
+ set link $itk_option(-helpdir)/[lindex $topic 1]
+ } else {
+ set link [lindex $topic 1]
+ }
+ $m add radiobutton -variable topic \
+ -value [lindex $topic 0] \
+ -label [lindex $topic 0] \
+ -command [list $this followlink $link]
+ }
+ }
+ $m add separator
+ $m add command -label "Close Help" -underline 0 \
+ -command $itk_option(-closecmd)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -title
+#
+# Specify the window title.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hyperhelp::title {
+ wm title $itk_component(hull) $itk_option(-title)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -helpdir
+#
+# Set location of help files
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hyperhelp::helpdir {
+ if {[file pathtype $itk_option(-helpdir)] == "relative"} {
+ configure -helpdir [file join [pwd] $itk_option(-helpdir)]
+ } else {
+ set _history {}
+ set _history_len 0
+ set _history_ndx -1
+ $itk_component(navmenu) entryconfig 0 -state disabled
+ $itk_component(navmenu) entryconfig 1 -state disabled
+ configure -topics $itk_option(-topics)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -closecmd
+#
+# Specify the command to execute when close is selected from the menu
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Hyperhelp::closecmd {
+ $itk_component(topicmenu) entryconfigure last -command $itk_option(-closecmd)
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: showtopic topic
+#
+# render text of help topic <topic>. The text is expected to be found in
+# <helpdir>/<topic>.html
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::showtopic {topic} {
+ if ![regexp {(.*)#(.*)} $topic dummy topicname anchorpart] {
+ set topicname $topic
+ set anchorpart {}
+ }
+ if {$topicname == ""} {
+ set topicname $_file
+ set filepath $_file
+ } else {
+ set filepath $itk_option(-helpdir)/$topicname.html
+ }
+ if {[incr _history_ndx] < $itk_option(-maxhistory)} {
+ set _history [lrange $_history 0 [expr {$_history_ndx - 1}]]
+ set _history_len [expr {$_history_ndx + 1}]
+ } else {
+ incr _history_ndx -1
+ set _history [lrange $_history 1 $_history_ndx]
+ set _history_len [expr {$_history_ndx + 1}]
+ }
+ lappend _history [list $topicname $filepath $anchorpart]
+ _readtopic $filepath $anchorpart
+}
+
+# ------------------------------------------------------------------
+# METHOD: followlink link
+#
+# Callback for click on a link. Shows new topic.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::followlink {link} {
+ if {[string compare $beforelink ""] != 0} {
+ eval $beforelink $link
+ }
+ if ![regexp {(.*)#(.*)} $link dummy filepart anchorpart] {
+ set filepart $link
+ set anchorpart {}
+ }
+ if {$filepart != "" && [string index [file dirname $filepart] 0] != "/" && \
+ [string index [file dirname $filepart] 0] != "~"} {
+ set filepart [$itk_component(scrtxt) pwd]/$filepart
+ set hfile $filepart
+ } else {
+ set hfile $_file
+ }
+ incr _history_ndx
+ set _history [lrange $_history 0 [expr {$_history_ndx - 1}]]
+ set _history_len [expr {$_history_ndx + 1}]
+ lappend _history [list [file rootname [file tail $hfile]] $hfile $anchorpart]
+ set ret [_readtopic $filepart $anchorpart]
+ if {[string compare $afterlink ""] != 0} {
+ eval $afterlink $link
+ }
+ return $ret
+}
+
+# ------------------------------------------------------------------
+# METHOD: forward
+#
+# Show topic one forward in history list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::forward {} {
+ if {$_rendering || ($_history_ndx+1) >= $_history_len} return
+ incr _history_ndx
+ eval _readtopic [lrange [lindex $_history $_history_ndx] 1 end]
+}
+
+# ------------------------------------------------------------------
+# METHOD: back
+#
+# Show topic one back in history list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::back {} {
+ if {$_rendering || $_history_ndx <= 0} return
+ incr _history_ndx -1
+ set _histdir 1
+ eval _readtopic [lrange [lindex $_history $_history_ndx] 1 end]
+}
+
+# ------------------------------------------------------------------
+# METHOD: updatefeedback remaining
+#
+# Callback from text to update feedback widget
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::updatefeedback {n} {
+ if {($_remaining - $n) > .1*$_len} {
+ [$itk_interior.feedbackshell childsite].helpfeedback step [expr {$_remaining - $n}]
+ update idletasks
+ set _remaining $n
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _readtopic
+#
+# Read in file, render it in text area, and jump to anchorpoint
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::_readtopic {file {anchorpoint {}}} {
+ if {$file != ""} {
+ if {[string compare $file $_file] != 0} {
+ if {[catch {set f [open $file r]} err]} {
+ incr _history_ndx $_histdir
+ set _history_len [expr {$_history_ndx + 1}]
+ set _histdir -1
+ set m $itk_component(navmenu)
+ if {($_history_ndx+1) < $_history_len} {
+ $m entryconfig 0 -state normal
+ } else {
+ $m entryconfig 0 -state disabled
+ }
+ if {$_history_ndx > 0} {
+ $m entryconfig 1 -state normal
+ } else {
+ $m entryconfig 1 -state disabled
+ }
+ return
+ }
+ set _file $file
+ set txt [read $f]
+ iwidgets::shell $itk_interior.feedbackshell -title \
+ "Rendering HTML" -padx 1 -pady 1
+ iwidgets::Feedback [$itk_interior.feedbackshell \
+ childsite].helpfeedback \
+ -steps [set _len [string length $txt]] \
+ -labeltext "Rendering HTML" -labelpos n
+ pack [$itk_interior.feedbackshell childsite].helpfeedback
+ $itk_interior.feedbackshell center $itk_interior
+ $itk_interior.feedbackshell activate
+ set _remaining $_len
+ set _rendering 1
+ if {[catch {$itk_component(scrtxt) render $txt [file dirname \
+ $file]} err]} {
+ if [regexp "</pre>" $err] {
+ $itk_component(scrtxt) render "<tt>$err</tt>"
+ } else {
+ $itk_component(scrtxt) render "<pre>$err</pre>"
+ }
+ }
+ wm title $itk_component(hull) "Help: $file"
+ itcl::delete object [$itk_interior.feedbackshell \
+ childsite].helpfeedback
+ itcl::delete object $itk_interior.feedbackshell
+ set _rendering 0
+ }
+ }
+ set m $itk_component(navmenu)
+ if {($_history_ndx+1) < $_history_len} {
+ $m entryconfig 0 -state normal
+ } else {
+ $m entryconfig 0 -state disabled
+ }
+ if {$_history_ndx > 0} {
+ $m entryconfig 1 -state normal
+ } else {
+ $m entryconfig 1 -state disabled
+ }
+ if {$anchorpoint != {}} {
+ $itk_component(scrtxt) import -link #$anchorpoint
+ } else {
+ $itk_component(scrtxt) import -link #
+ }
+ set _histdir -1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _fill_go_menu
+#
+# update go submenu with current history
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::_fill_go_menu {} {
+ set m $itk_component(navgo)
+ catch {$m delete 0 last}
+ for {set i [expr {$_history_len - 1}]} {$i >= 0} {incr i -1} {
+ set topic [lindex [lindex $_history $i] 0]
+ set filepath [lindex [lindex $_history $i] 1]
+ set anchor [lindex [lindex $_history $i] 2]
+ $m add command -label $topic \
+ -command [list $this followlink $filepath#$anchor]
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _pageforward
+#
+# Callback for page forward shortcut key
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::_pageforward {} {
+ $itk_component(scrtxt) yview scroll 1 pages
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _pageback
+#
+# Callback for page back shortcut key
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::_pageback {} {
+ $itk_component(scrtxt) yview scroll -1 pages
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _lineforward
+#
+# Callback for line forward shortcut key
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::_lineforward {} {
+ $itk_component(scrtxt) yview scroll 1 units
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _lineback
+#
+# Callback for line back shortcut key
+# ------------------------------------------------------------------
+itcl::body iwidgets::Hyperhelp::_lineback {} {
+ $itk_component(scrtxt) yview scroll -1 units
+}
diff --git a/iwidgets/generic/labeledframe.itk b/iwidgets/generic/labeledframe.itk
new file mode 100644
index 00000000000..59aa501707c
--- /dev/null
+++ b/iwidgets/generic/labeledframe.itk
@@ -0,0 +1,496 @@
+#
+# Labeledframe
+# ----------------------------------------------------------------------
+# Implements a hull frame with a grooved relief, a label, and a
+# frame childsite.
+#
+# The frame childsite can be filled with any widget via a derived class
+# or though the use of the childsite method. This class was designed
+# to be a general purpose base class for supporting the combination of
+# a labeled frame and a childsite. The options include the ability to
+# position the label at configurable locations within the grooved relief
+# of the hull frame, and control the display of the label.
+#
+# To following demonstrates the different values which the "-labelpos"
+# option may be set to and the resulting layout of the label when
+# one executes the following command with "-labeltext" set to "LABEL":
+#
+# example:
+# labeledframe .w -labeltext LABEL -labelpos <ne,n,nw,se,s,sw,en,e,es,wn,s,ws>
+#
+# ne n nw se s sw
+#
+# *LABEL**** **LABEL** ****LABEL* ********** ********* **********
+# * * * * * * * * * * * *
+# * * * * * * * * * * * *
+# * * * * * * * * * * * *
+# ********** ********* ********** *LABEL**** **LABEL** ****LABEL*
+#
+# en e es wn s ws
+#
+# ********** ********* ********* ********* ********* **********
+# * * * * * * * * * * * *
+# L * * * * * * L * * * *
+# A * L * * * * A * L * L
+# B * A * L * * B * A * A
+# E * B * A * * E * B * B
+# L * E * B * * L * E * E
+# * * L * E * * * * L * L
+# * * * * L * * * * * * *
+# ********** ********** ********* ********** ********* **********
+#
+# ----------------------------------------------------------------------
+# AUTHOR: John A. Tucker EMAIL: jatucker@spd.dsccc.com
+#
+# ======================================================================
+# Copyright (c) 1997 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.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Labeledframe.labelMargin 10 widgetDefault
+option add *Labeledframe.labelFont \
+ "-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*" widgetDefault
+option add *Labeledframe.labelPos n widgetDefault
+option add *Labeledframe.borderWidth 2 widgetDefault
+option add *Labeledframe.relief groove widgetDefault
+
+
+#
+# Usual options.
+#
+itk::usual Labeledframe {
+ keep -background -cursor -labelfont -foreground
+}
+
+itcl::class iwidgets::Labeledframe {
+
+ inherit itk::Archetype
+
+ itk_option define -ipadx iPadX IPad 0
+ itk_option define -ipady iPadY IPad 0
+
+ itk_option define -labelmargin labelMargin LabelMargin 10
+ itk_option define -labelpos labelPos LabelPos n
+
+ constructor {args} {}
+ destructor {}
+
+ #
+ # Public methods
+ #
+ public method childsite {}
+
+ #
+ # Protected methods
+ #
+ protected {
+ method _positionLabel {{when later}}
+ method _collapseMargin {}
+ method _setMarginThickness {value}
+ method smt {value} { _setMarginThickness $value }
+ }
+
+ #
+ # Private methods/data
+ #
+ private {
+ proc _initTable {}
+
+ variable _reposition "" ;# non-null => _positionLabel pending
+ variable itk_hull ""
+
+ common _LAYOUT_TABLE
+ }
+}
+
+#
+# Provide a lowercased access method for the Labeledframe class.
+#
+proc ::iwidgets::labeledframe {pathName args} {
+ uplevel ::iwidgets::Labeledframe $pathName $args
+}
+
+# -----------------------------------------------------------------------------
+# CONSTRUCTOR
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Labeledframe::constructor { args } {
+ #
+ # Create a window with the same name as this object
+ #
+ set itk_hull [namespace tail $this]
+ set itk_interior $itk_hull
+
+ itk_component add hull {
+ frame $itk_hull \
+ -relief groove \
+ -class [namespace tail [info class]]
+ } {
+ keep -background -cursor -relief -borderwidth
+ rename -highlightbackground -background background Background
+ rename -highlightcolor -background background Background
+ }
+ bind itk-delete-$itk_hull <Destroy> "itcl::delete object $this"
+
+ set tags [bindtags $itk_hull]
+ bindtags $itk_hull [linsert $tags 0 itk-delete-$itk_hull]
+
+ #
+ # Create the childsite frame window
+ # _______
+ # |_____|
+ # |_|X|_|
+ # |_____|
+ #
+ itk_component add childsite {
+ frame $itk_interior.childsite -highlightthickness 0 -bd 0
+ }
+
+ #
+ # Create the label to be positioned within the grooved relief
+ # of the hull frame.
+ #
+ itk_component add label {
+ label $itk_interior.label -highlightthickness 0 -bd 0
+ } {
+ usual
+ rename -bitmap -labelbitmap labelBitmap Bitmap
+ rename -font -labelfont labelFont Font
+ rename -image -labelimage labelImage Image
+ rename -text -labeltext labelText Text
+ rename -textvariable -labelvariable labelVariable Variable
+ ignore -highlightthickness -highlightcolor
+ }
+
+ grid $itk_component(childsite) -row 1 -column 1 -sticky nsew
+ grid columnconfigure $itk_interior 1 -weight 1
+ grid rowconfigure $itk_interior 1 -weight 1
+
+ bind $itk_component(label) <Configure> +[itcl::code $this _positionLabel]
+
+ #
+ # Initialize the class array of layout configuration options. Since
+ # this is a one time only thing.
+ #
+ _initTable
+
+ eval itk_initialize $args
+
+ #
+ # When idle, position the label.
+ #
+ _positionLabel
+}
+
+# -----------------------------------------------------------------------------
+# DESTRUCTOR
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Labeledframe::destructor {} {
+
+ if {$_reposition != ""} {
+ after cancel $_reposition
+ }
+
+ if {[winfo exists $itk_hull]} {
+ set tags [bindtags $itk_hull]
+ set i [lsearch $tags itk-delete-$itk_hull]
+ if {$i >= 0} {
+ bindtags $itk_hull [lreplace $tags $i $i]
+ }
+ destroy $itk_hull
+ }
+}
+
+# -----------------------------------------------------------------------------
+# OPTIONS
+# -----------------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -ipadx
+#
+# Specifies the width of the horizontal gap from the border to the
+# the child site.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledframe::ipadx {
+ grid configure $itk_component(childsite) -padx $itk_option(-ipadx)
+ _positionLabel
+}
+
+# ------------------------------------------------------------------
+# OPTION: -ipady
+#
+# Specifies the width of the vertical gap from the border to the
+# the child site.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledframe::ipady {
+ grid configure $itk_component(childsite) -pady $itk_option(-ipady)
+ _positionLabel
+}
+
+# -----------------------------------------------------------------------------
+# OPTION: -labelmargin
+#
+# Set the margin of the most adjacent side of the label to the hull
+# relief.
+# ----------------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledframe::labelmargin {
+ _positionLabel
+}
+
+# -----------------------------------------------------------------------------
+# OPTION: -labelpos
+#
+# Set the position of the label within the relief of the hull frame
+# widget.
+# ----------------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledframe::labelpos {
+ _positionLabel
+}
+
+# -----------------------------------------------------------------------------
+# PROCS
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# PRIVATE PROC: _initTable
+#
+# Initializes the _LAYOUT_TABLE common variable of the Labeledframe
+# class. The initialization is performed in its own proc ( as opposed
+# to in the class definition ) so that the initialization occurs only
+# once.
+#
+# _LAYOUT_TABLE common array description:
+# Provides a table of the configuration option values
+# used to place the label widget within the grooved relief of the hull
+# frame for each of the 12 possible "-labelpos" values.
+#
+# Each of the 12 rows is layed out as follows:
+# {"-relx" "-rely" <rowconfigure|columnconfigure> <row/column number>}
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Labeledframe::_initTable {} {
+ array set _LAYOUT_TABLE {
+ nw-relx 0.0 nw-rely 0.0 nw-wrap 0 nw-conf rowconfigure nw-num 0
+ n-relx 0.5 n-rely 0.0 n-wrap 0 n-conf rowconfigure n-num 0
+ ne-relx 1.0 ne-rely 0.0 ne-wrap 0 ne-conf rowconfigure ne-num 0
+
+ sw-relx 0.0 sw-rely 1.0 sw-wrap 0 sw-conf rowconfigure sw-num 2
+ s-relx 0.5 s-rely 1.0 s-wrap 0 s-conf rowconfigure s-num 2
+ se-relx 1.0 se-rely 1.0 se-wrap 0 se-conf rowconfigure se-num 2
+
+ en-relx 1.0 en-rely 0.0 en-wrap 1 en-conf columnconfigure en-num 2
+ e-relx 1.0 e-rely 0.5 e-wrap 1 e-conf columnconfigure e-num 2
+ es-relx 1.0 es-rely 1.0 es-wrap 1 es-conf columnconfigure es-num 2
+
+ wn-relx 0.0 wn-rely 0.0 wn-wrap 1 wn-conf columnconfigure wn-num 0
+ w-relx 0.0 w-rely 0.5 w-wrap 1 w-conf columnconfigure w-num 0
+ ws-relx 0.0 ws-rely 1.0 ws-wrap 1 ws-conf columnconfigure ws-num 0
+ }
+
+ #
+ # Since this is a one time only thing, we'll redefine the proc to be empty
+ # afterwards so it only happens once.
+ #
+ # NOTE: Be careful to use the "body" command, or the proc will get lost!
+ #
+ itcl::body ::iwidgets::Labeledframe::_initTable {} {}
+}
+
+# -----------------------------------------------------------------------------
+# METHODS
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# PUBLIC METHOD:: childsite
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Labeledframe::childsite {} {
+ return $itk_component(childsite)
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: _positionLabel ?when?
+#
+# Places the label in the relief of the hull. If "when" is "now", the
+# change is applied immediately. If it is "later" or it is not
+# specified, then the change is applied later, when the application
+# is idle.
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Labeledframe::_positionLabel {{when later}} {
+
+ if {$when == "later"} {
+ if {$_reposition == ""} {
+ set _reposition [after idle [itcl::code $this _positionLabel now]]
+ }
+ return
+ }
+
+ set pos $itk_option(-labelpos)
+
+ #
+ # If there is not an entry for the "relx" value associated with
+ # the given "-labelpos" option value, then it invalid.
+ #
+ if { [catch {set relx $_LAYOUT_TABLE($pos-relx)}] } {
+ error "bad labelpos option\"$itk_option(-labelpos)\": should be\
+ nw, n, ne, sw, s, se, en, e, es, wn, w, or ws"
+ }
+
+ update idletasks
+ $itk_component(label) configure -wraplength $_LAYOUT_TABLE($pos-wrap)
+ set labelWidth [winfo reqwidth $itk_component(label)]
+ set labelHeight [winfo reqheight $itk_component(label)]
+ set borderwidth $itk_option(-borderwidth)
+ set margin $itk_option(-labelmargin)
+
+ switch $pos {
+ nw {
+ set labelThickness $labelHeight
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos [expr {$minsize+$borderwidth+$margin}]
+ set yPos -$minsize
+ }
+ n {
+ set labelThickness $labelHeight
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos [expr {-$labelWidth/2.0}]
+ set yPos -$minsize
+ }
+ ne {
+ set labelThickness $labelHeight
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos [expr {-($minsize+$borderwidth+$margin+$labelWidth)}]
+ set yPos -$minsize
+ }
+
+ sw {
+ set labelThickness $labelHeight
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos [expr {$minsize+$borderwidth+$margin}]
+ set yPos -$minsize
+ }
+ s {
+ set labelThickness $labelHeight
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos [expr {-$labelWidth/2.0}]
+ set yPos [expr {-$labelHeight/2.0}]
+ }
+ se {
+ set labelThickness $labelHeight
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos [expr {-($minsize+$borderwidth+$margin+$labelWidth)}]
+ set yPos [expr {-$labelHeight/2.0}]
+ }
+
+ wn {
+ set labelThickness $labelWidth
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos -$minsize
+ set yPos [expr {$minsize+$margin+$borderwidth}]
+ }
+ w {
+ set labelThickness $labelWidth
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos -$minsize
+ set yPos [expr {-($labelHeight/2.0)}]
+ }
+ ws {
+ set labelThickness $labelWidth
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos -$minsize
+ set yPos [expr {-($minsize+$borderwidth+$margin+$labelHeight)}]
+ }
+
+ en {
+ set labelThickness $labelWidth
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos -$minsize
+ set yPos [expr {$minsize+$borderwidth+$margin}]
+ }
+ e {
+ set labelThickness $labelWidth
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos -$minsize
+ set yPos [expr {-($labelHeight/2.0)}]
+ }
+ es {
+ set labelThickness $labelWidth
+ set minsize [expr {$labelThickness/2.0}]
+ set xPos -$minsize
+ set yPos [expr {-($minsize+$borderwidth+$margin+$labelHeight)}]
+ }
+ }
+ _setMarginThickness $minsize
+
+ place $itk_component(label) \
+ -relx $_LAYOUT_TABLE($pos-relx) -x $xPos \
+ -rely $_LAYOUT_TABLE($pos-rely) -y $yPos \
+ -anchor nw
+
+ set what $_LAYOUT_TABLE($pos-conf)
+ set number $_LAYOUT_TABLE($pos-num)
+
+ grid $what $itk_interior $number -minsize $minsize
+
+ set _reposition ""
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: _collapseMargin
+#
+# Resets the "-minsize" of all rows and columns of the hull's grid
+# used to set the label margin to 0
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Labeledframe::_collapseMargin {} {
+ grid columnconfigure $itk_interior 0 -minsize 0
+ grid columnconfigure $itk_interior 2 -minsize 0
+ grid rowconfigure $itk_interior 0 -minsize 0
+ grid rowconfigure $itk_interior 2 -minsize 0
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: _setMarginThickness
+#
+# Set the margin thickness ( i.e. the hidden "-highlightthickness"
+# of the hull ) to the input value.
+#
+# The "-highlightthickness" option of the hull frame is not intended to be
+# configured by users of this class, but does need to be configured to properly
+# place the label whenever the label is configured.
+#
+# Therefore, since I can't find a better way at this time, I achieve this
+# configuration by: adding the "-highlightthickness" option back into
+# the hull frame; configuring the "-highlightthickness" option to properly
+# place the label; and then remove the "-highlightthickness" option from the
+# hull.
+#
+# This way the option is not visible or configurable without some hacking.
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Labeledframe::_setMarginThickness {value} {
+ itk_option add hull.highlightthickness
+ $itk_component(hull) configure -highlightthickness $value
+ itk_option remove hull.highlightthickness
+}
+
+
diff --git a/iwidgets/generic/labeledwidget.itk b/iwidgets/generic/labeledwidget.itk
new file mode 100644
index 00000000000..2e0faa5d21d
--- /dev/null
+++ b/iwidgets/generic/labeledwidget.itk
@@ -0,0 +1,445 @@
+#
+# Labeledwidget
+# ----------------------------------------------------------------------
+# Implements a labeled widget which contains a label and child site.
+# The child site is a frame which can filled with any widget via a
+# derived class or though the use of the childsite method. This class
+# was designed to be a general purpose base class for supporting the
+# combination of label widget and a childsite, where a label may be
+# text, bitmap or image. The options include the ability to position
+# the label around the childsite widget, modify the font and margin,
+# and control the display of the label.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Labeledwidget {
+ keep -background -cursor -foreground -labelfont
+}
+
+# ------------------------------------------------------------------
+# LABELEDWIDGET
+# ------------------------------------------------------------------
+itcl::class iwidgets::Labeledwidget {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -disabledforeground disabledForeground \
+ DisabledForeground \#a3a3a3
+ itk_option define -labelpos labelPos Position w
+ itk_option define -labelmargin labelMargin Margin 2
+ itk_option define -labeltext labelText Text {}
+ itk_option define -labelvariable labelVariable Variable {}
+ itk_option define -labelbitmap labelBitmap Bitmap {}
+ itk_option define -labelimage labelImage Image {}
+ itk_option define -state state State normal
+ itk_option define -sticky sticky Sticky nsew
+
+ public method childsite
+
+ private method _positionLabel {{when later}}
+
+ proc alignlabels {args} {}
+
+ protected variable _reposition "" ;# non-null => _positionLabel pending
+}
+
+#
+# Provide a lowercased access method for the Labeledwidget class.
+#
+proc ::iwidgets::labeledwidget {pathName args} {
+ uplevel ::iwidgets::Labeledwidget $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Labeledwidget::constructor {args} {
+ #
+ # Create a frame for the childsite widget.
+ #
+ itk_component add -protected lwchildsite {
+ frame $itk_interior.lwchildsite
+ }
+
+ #
+ # Create label.
+ #
+ itk_component add label {
+ label $itk_interior.label
+ } {
+ usual
+
+ rename -font -labelfont labelFont Font
+ ignore -highlightcolor -highlightthickness
+ }
+
+ #
+ # Set the interior to be the childsite for derived classes.
+ #
+ set itk_interior $itk_component(lwchildsite)
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+
+ #
+ # When idle, position the label.
+ #
+ _positionLabel
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Labeledwidget::destructor {} {
+ if {$_reposition != ""} {after cancel $_reposition}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -disabledforeground
+#
+# Specified the foreground to be used on the label when disabled.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledwidget::disabledforeground {}
+
+# ------------------------------------------------------------------
+# OPTION: -labelpos
+#
+# Set the position of the label on the labeled widget. The margin
+# between the label and childsite comes along for the ride.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledwidget::labelpos {
+ _positionLabel
+}
+
+# ------------------------------------------------------------------
+# OPTION: -labelmargin
+#
+# Specifies the distance between the widget and label.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledwidget::labelmargin {
+ _positionLabel
+}
+
+# ------------------------------------------------------------------
+# OPTION: -labeltext
+#
+# Specifies the label text.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledwidget::labeltext {
+ $itk_component(label) configure -text $itk_option(-labeltext)
+
+ _positionLabel
+}
+
+# ------------------------------------------------------------------
+# OPTION: -labelvariable
+#
+# Specifies the label text variable.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledwidget::labelvariable {
+ $itk_component(label) configure -textvariable $itk_option(-labelvariable)
+
+ _positionLabel
+}
+
+# ------------------------------------------------------------------
+# OPTION: -labelbitmap
+#
+# Specifies the label bitmap.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledwidget::labelbitmap {
+ $itk_component(label) configure -bitmap $itk_option(-labelbitmap)
+
+ _positionLabel
+}
+
+# ------------------------------------------------------------------
+# OPTION: -labelimage
+#
+# Specifies the label image.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledwidget::labelimage {
+ $itk_component(label) configure -image $itk_option(-labelimage)
+
+ _positionLabel
+}
+
+# ------------------------------------------------------------------
+# OPTION: -sticky
+#
+# Specifies the stickyness of the child site. This option was added
+# by James Bonfield (committed by Chad Smith 8/20/01).
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledwidget::sticky {
+ grid $itk_component(lwchildsite) -sticky $itk_option(-sticky)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -state
+#
+# Specifies the state of the label.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Labeledwidget::state {
+ _positionLabel
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Returns the path name of the child site widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Labeledwidget::childsite {} {
+ return $itk_component(lwchildsite)
+}
+
+# ------------------------------------------------------------------
+# PROCEDURE: alignlabels widget ?widget ...?
+#
+# The alignlabels procedure takes a list of widgets derived from
+# the Labeledwidget class and adjusts the label margin to align
+# the labels.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Labeledwidget::alignlabels {args} {
+ update
+ set maxLabelWidth 0
+
+ #
+ # Verify that all the widgets are of type Labeledwidget and
+ # determine the size of the maximum length label string.
+ #
+ foreach iwid $args {
+ set objcmd [itcl::find objects -isa Labeledwidget *::$iwid]
+
+ if {$objcmd == ""} {
+ error "$iwid is not a \"Labeledwidget\""
+ }
+
+ set csWidth [winfo reqwidth $iwid.lwchildsite]
+ set shellWidth [winfo reqwidth $iwid]
+
+ if {($shellWidth - $csWidth) > $maxLabelWidth} {
+ set maxLabelWidth [expr {$shellWidth - $csWidth}]
+ }
+ }
+
+ #
+ # Adjust the margins for the labels such that the child sites and
+ # labels line up.
+ #
+ foreach iwid $args {
+ set csWidth [winfo reqwidth $iwid.lwchildsite]
+ set shellWidth [winfo reqwidth $iwid]
+
+ set labelSize [expr {$shellWidth - $csWidth}]
+
+ if {$maxLabelWidth > $labelSize} {
+ set objcmd [itcl::find objects -isa Labeledwidget *::$iwid]
+ set dist [expr {$maxLabelWidth - \
+ ($labelSize - [$objcmd cget -labelmargin])}]
+
+ $objcmd configure -labelmargin $dist
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _positionLabel ?when?
+#
+# Packs the label and label margin. If "when" is "now", the
+# change is applied immediately. If it is "later" or it is not
+# specified, then the change is applied later, when the application
+# is idle.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Labeledwidget::_positionLabel {{when later}} {
+ if {$when == "later"} {
+ if {$_reposition == ""} {
+ set _reposition [after idle [itcl::code $this _positionLabel now]]
+ }
+ return
+
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ #
+ # If we have a label, be it text, bitmap, or image continue.
+ #
+ if {($itk_option(-labeltext) != {}) || \
+ ($itk_option(-labelbitmap) != {}) || \
+ ($itk_option(-labelimage) != {}) || \
+ ($itk_option(-labelvariable) != {})} {
+
+ #
+ # Set the foreground color based on the state.
+ #
+ if {[info exists itk_option(-state)]} {
+ switch -- $itk_option(-state) {
+ disabled {
+ $itk_component(label) configure \
+ -foreground $itk_option(-disabledforeground)
+ }
+ normal {
+ $itk_component(label) configure \
+ -foreground $itk_option(-foreground)
+ }
+ }
+ }
+
+ set parent [winfo parent $itk_component(lwchildsite)]
+
+ #
+ # Switch on the label position option. Using the grid,
+ # adjust the row/column setting of the label, margin, and
+ # and childsite. The margin height/width is adjust based
+ # on the orientation as well. Finally, set the weights such
+ # that the childsite takes the heat on expansion and shrinkage.
+ #
+ switch $itk_option(-labelpos) {
+ nw -
+ n -
+ ne {
+ grid $itk_component(label) -row 0 -column 0 \
+ -sticky $itk_option(-labelpos)
+ grid $itk_component(lwchildsite) -row 2 -column 0 \
+ -sticky $itk_option(-sticky)
+
+ grid rowconfigure $parent 0 -weight 0 -minsize 0
+ grid rowconfigure $parent 1 -weight 0 -minsize \
+ [winfo pixels $itk_component(label) \
+ $itk_option(-labelmargin)]
+ grid rowconfigure $parent 2 -weight 1 -minsize 0
+
+ grid columnconfigure $parent 0 -weight 1 -minsize 0
+ grid columnconfigure $parent 1 -weight 0 -minsize 0
+ grid columnconfigure $parent 2 -weight 0 -minsize 0
+ }
+
+ en -
+ e -
+ es {
+ grid $itk_component(lwchildsite) -row 0 -column 0 \
+ -sticky $itk_option(-sticky)
+ grid $itk_component(label) -row 0 -column 2 \
+ -sticky $itk_option(-labelpos)
+
+ grid rowconfigure $parent 0 -weight 1 -minsize 0
+ grid rowconfigure $parent 1 -weight 0 -minsize 0
+ grid rowconfigure $parent 2 -weight 0 -minsize 0
+
+ grid columnconfigure $parent 0 -weight 1 -minsize 0
+ grid columnconfigure $parent 1 -weight 0 -minsize \
+ [winfo pixels $itk_component(label) \
+ $itk_option(-labelmargin)]
+ grid columnconfigure $parent 2 -weight 0 -minsize 0
+ }
+
+ se -
+ s -
+ sw {
+ grid $itk_component(lwchildsite) -row 0 -column 0 \
+ -sticky $itk_option(-sticky)
+ grid $itk_component(label) -row 2 -column 0 \
+ -sticky $itk_option(-labelpos)
+
+ grid rowconfigure $parent 0 -weight 1 -minsize 0
+ grid rowconfigure $parent 1 -weight 0 -minsize \
+ [winfo pixels $itk_component(label) \
+ $itk_option(-labelmargin)]
+ grid rowconfigure $parent 2 -weight 0 -minsize 0
+
+ grid columnconfigure $parent 0 -weight 1 -minsize 0
+ grid columnconfigure $parent 1 -weight 0 -minsize 0
+ grid columnconfigure $parent 2 -weight 0 -minsize 0
+ }
+
+ wn -
+ w -
+ ws {
+ grid $itk_component(lwchildsite) -row 0 -column 2 \
+ -sticky $itk_option(-sticky)
+ grid $itk_component(label) -row 0 -column 0 \
+ -sticky $itk_option(-labelpos)
+
+ grid rowconfigure $parent 0 -weight 1 -minsize 0
+ grid rowconfigure $parent 1 -weight 0 -minsize 0
+ grid rowconfigure $parent 2 -weight 0 -minsize 0
+
+ grid columnconfigure $parent 0 -weight 0 -minsize 0
+ grid columnconfigure $parent 1 -weight 0 -minsize \
+ [winfo pixels $itk_component(label) \
+ $itk_option(-labelmargin)]
+ grid columnconfigure $parent 2 -weight 1 -minsize 0
+ }
+
+ default {
+ error "bad labelpos option\
+ \"$itk_option(-labelpos)\": should be\
+ nw, n, ne, sw, s, se, en, e, es, wn, w, or ws"
+ }
+ }
+
+ #
+ # Else, neither the label text, bitmap, or image have a value, so
+ # forget them so they don't appear and manage only the childsite.
+ #
+ } else {
+ grid forget $itk_component(label)
+
+ grid $itk_component(lwchildsite) -row 0 -column 0 -sticky $itk_option(-sticky)
+
+ set parent [winfo parent $itk_component(lwchildsite)]
+
+ grid rowconfigure $parent 0 -weight 1 -minsize 0
+ grid rowconfigure $parent 1 -weight 0 -minsize 0
+ grid rowconfigure $parent 2 -weight 0 -minsize 0
+ grid columnconfigure $parent 0 -weight 1 -minsize 0
+ grid columnconfigure $parent 1 -weight 0 -minsize 0
+ grid columnconfigure $parent 2 -weight 0 -minsize 0
+ }
+
+ #
+ # Reset the resposition flag.
+ #
+ set _reposition ""
+}
diff --git a/iwidgets/generic/mainwindow.itk b/iwidgets/generic/mainwindow.itk
new file mode 100644
index 00000000000..032021e76bb
--- /dev/null
+++ b/iwidgets/generic/mainwindow.itk
@@ -0,0 +1,313 @@
+#
+# Mainwindow
+# ----------------------------------------------------------------------
+# This class implements a mainwindow containing a menubar, toolbar,
+# mousebar, childsite, status line, and help line. Each item may
+# be filled and configured to suit individual needs.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) RCS: $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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.
+# ======================================================================
+
+# ------------------------------------------------------------------
+# MAINWINDOW
+# ------------------------------------------------------------------
+itcl::class iwidgets::Mainwindow {
+ inherit iwidgets::Shell
+
+ constructor {args} {}
+
+ itk_option define -helpline helpLine HelpLine 1
+ itk_option define -statusline statusLine StatusLine 1
+
+ public {
+ method childsite {}
+ method menubar {args}
+ method mousebar {args}
+ method msgd {args}
+ method toolbar {args}
+ }
+
+ protected {
+ method _exitCB {}
+
+ common _helpVar
+ common _statusVar
+ }
+}
+
+#
+# Provide a lowercased access method for the ::iwidgets::Mainwindow class.
+#
+proc iwidgets::mainwindow {pathName args} {
+ uplevel ::iwidgets::Mainwindow $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Mainwindow::constructor {args} {
+ itk_option add hull.width hull.height
+
+ pack propagate $itk_component(hull) no
+
+ wm protocol $itk_component(hull) WM_DELETE_WINDOW [itcl::code $this _exitCB]
+
+ #
+ # Create a menubar, renaming the font, foreground, and background
+ # so they may be separately set. The help variable will be setup
+ # as well.
+ #
+ itk_component add menubar {
+ iwidgets::Menubar $itk_interior.menubar \
+ -helpvariable [itcl::scope _helpVar($this)]
+ } {
+ keep -disabledforeground -cursor \
+ -highlightbackground -highlightthickness
+ rename -font \
+ -menubarfont menuBarFont Font
+ rename -foreground \
+ -menubarforeground menuBarForeground Foreground
+ rename -background \
+ -menubarbackground menuBarBackground Background
+ }
+
+ #
+ # Add a toolbar beneath the menubar.
+ #
+ itk_component add toolbar {
+ iwidgets::Toolbar $itk_interior.toolbar -orient horizontal \
+ -helpvariable [itcl::scope _helpVar($this)]
+ } {
+ keep -balloonbackground -balloondelay1 -balloondelay2 \
+ -balloonfont -balloonforeground -disabledforeground -cursor \
+ -highlightbackground -highlightthickness
+ rename -font -toolbarfont toolbarFont Font
+ rename -foreground -toolbarforeground toolbarForeground Foreground
+ rename -background -toolbarbackground toolbarBackground Background
+ }
+
+ #
+ # Add a mouse bar on the left.
+ #
+ itk_component add mousebar {
+ iwidgets::Toolbar $itk_interior.mousebar -orient vertical \
+ -helpvariable [itcl::scope _helpVar($this)]
+ } {
+ keep -balloonbackground -balloondelay1 -balloondelay2 \
+ -balloonfont -balloonforeground -disabledforeground -cursor \
+ -highlightbackground -highlightthickness
+ rename -font -toolbarfont toolbarFont Font
+ rename -foreground -toolbarforeground toolbarForeground Foreground
+ rename -background -toolbarbackground toolbarBackground Background
+ }
+
+ #
+ # Create the childsite window window.
+ #
+ itk_component add -protected mwchildsite {
+ frame $itk_interior.mwchildsite
+ }
+
+ #
+ # Add the help and system status lines
+ #
+ itk_component add -protected lineframe {
+ frame $itk_interior.lineframe
+ }
+
+ itk_component add help {
+ label $itk_component(lineframe).help \
+ -textvariable [itcl::scope _helpVar($this)] \
+ -relief sunken -borderwidth 2 -width 10
+ }
+
+ itk_component add status {
+ label $itk_component(lineframe).status \
+ -textvariable [itcl::scope _statusVar($this)] \
+ -relief sunken -borderwidth 2 -width 10
+ }
+
+ #
+ # Create the message dialog for use throughout the mainwindow.
+ #
+ itk_component add msgd {
+ iwidgets::Messagedialog $itk_interior.msgd -modality application
+ } {
+ usual
+ ignore -modality
+ }
+
+ #
+ # Use the grid to pack together the menubar, toolbar, mousebar,
+ # childsite, and status area.
+ #
+ grid $itk_component(menubar) -row 0 -column 0 -columnspan 2 -sticky ew
+ grid $itk_component(toolbar) -row 1 -column 0 -columnspan 2 -sticky ew
+ grid $itk_component(mousebar) -row 2 -column 0 -sticky ns
+ grid $itk_component(mwchildsite) -row 2 -column 1 -sticky nsew \
+ -padx 5 -pady 5
+ grid $itk_component(lineframe) -row 3 -column 0 -columnspan 2 -sticky ew
+
+ grid columnconfigure $itk_interior 1 -weight 1
+ grid rowconfigure $itk_interior 2 -weight 1
+
+ #
+ # Set the interior to be the childsite for derived classes.
+ #
+ set itk_interior $itk_component(mwchildsite)
+
+ #
+ # Initialize all the configuration options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -helpline
+#
+# Specifies whether or not to display the help line. The value
+# may be given in any of the forms acceptable to Tk_GetBoolean.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Mainwindow::helpline {
+ if {$itk_option(-helpline)} {
+ pack $itk_component(help) -side left -fill x -expand yes -padx 2
+ } else {
+ pack forget $itk_component(help)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -statusline
+#
+# Specifies whether or not to display the status line. The value
+# may be given in any of the forms acceptable to Tk_GetBoolean.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Mainwindow::statusline {
+ if {$itk_option(-statusline)} {
+ pack $itk_component(status) -side right -fill x -expand yes -padx 2
+ } else {
+ pack forget $itk_component(status)
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Return the childsite widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Mainwindow::childsite {} {
+ return $itk_component(mwchildsite)
+}
+
+# ------------------------------------------------------------------
+# METHOD: menubar ?args?
+#
+# Evaluate the args against the Menubar component.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Mainwindow::menubar {args} {
+ if {[llength $args] == 0} {
+ return $itk_component(menubar)
+ } else {
+ return [eval $itk_component(menubar) $args]
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: toolbar ?args?
+#
+# Evaluate the args against the Toolbar component.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Mainwindow::toolbar {args} {
+ if {[llength $args] == 0} {
+ return $itk_component(toolbar)
+ } else {
+ return [eval $itk_component(toolbar) $args]
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: mousebar ?args?
+#
+# Evaluate the args against the Mousebar component.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Mainwindow::mousebar {args} {
+ if {[llength $args] == 0} {
+ return $itk_component(mousebar)
+ } else {
+ return [eval $itk_component(mousebar) $args]
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: msgd ?args?
+#
+# Evaluate the args against the Messagedialog component.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Mainwindow::msgd {args} {
+ if {[llength $args] == 0} {
+ return $itk_component(msgd)
+ } else {
+ return [eval $itk_component(msgd) $args]
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _exitCB
+#
+# Menu callback for the exit option from the file menu. The method
+# confirms the user's request to exit the application prior to
+# taking the action.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Mainwindow::_exitCB {} {
+ #
+ # Configure the message dialog for confirmation of the exit request.
+ #
+ msgd configure -title Confirmation -bitmap questhead \
+ -text "Exit confirmation\n\
+ Are you sure ?"
+ msgd buttonconfigure OK -text Yes
+ msgd buttonconfigure Cancel -text No
+ msgd default Cancel
+ msgd center $itk_component(hull)
+
+ #
+ # Activate the message dialog and given a positive response
+ # proceed to exit the application
+ #
+ if {[msgd activate]} {
+ ::exit
+ }
+}
diff --git a/iwidgets/generic/menubar.itk b/iwidgets/generic/menubar.itk
new file mode 100644
index 00000000000..ca2d2001075
--- /dev/null
+++ b/iwidgets/generic/menubar.itk
@@ -0,0 +1,2267 @@
+#
+# Menubar widget
+# ----------------------------------------------------------------------
+# The Menubar command creates a new window (given by the pathName
+# argument) and makes it into a Pull down menu widget. Additional
+# options, described above may be specified on the command line or
+# in the option database to configure aspects of the Menubar such
+# as its colors and font. The Menubar command returns its pathName
+# argument. At the time this command is invoked, there must not exist
+# a window named pathName, but pathName's parent must exist.
+#
+# A Menubar is a widget that simplifies the task of creating
+# menu hierarchies. It encapsulates a frame widget, as well
+# as menubuttons, menus, and menu entries. The Menubar allows
+# menus to be specified and refer enced in a more consistent
+# manner than using Tk to build menus directly. First, Menubar
+# allows a menu tree to be expressed in a hierachical "language".
+# The Menubar accepts a menuButtons option that allows a list of
+# menubuttons to be added to the Menubar. In turn, each menubutton
+# accepts a menu option that spec ifies a list of menu entries
+# to be added to the menubutton's menu (as well as an option
+# set for the menu). Cascade entries in turn, accept a menu
+# option that specifies a list of menu entries to be added to
+# the cascade's menu (as well as an option set for the menu). In
+# this manner, a complete menu grammar can be expressed to the
+# Menubar. Additionally, the Menubar allows each component of
+# the Menubar system to be referenced by a simple componentPathName
+# syntax. Finally, the Menubar extends the option set of menu
+# entries to include the helpStr option used to implement status
+# bar help.
+#
+# WISH LIST:
+# This section lists possible future enhancements.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Bill W. Scott
+#
+# CURRENT MAINTAINER: Chad Smith --> csmith@adc.com or itclguy@yahoo.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Menubar {
+ keep -activebackground -activeborderwidth -activeforeground \
+ -anchor -background -borderwidth -cursor -disabledforeground \
+ -font -foreground -highlightbackground -highlightthickness \
+ -highlightcolor -justify -padx -pady -wraplength
+}
+
+itcl::class iwidgets::Menubar {
+ inherit itk::Widget
+
+ constructor { args } {}
+
+ itk_option define -foreground foreground Foreground Black
+ itk_option define -activebackground activeBackground Foreground "#ececec"
+ itk_option define -activeborderwidth activeBorderWidth BorderWidth 2
+ itk_option define -activeforeground activeForeground Background black
+ itk_option define -anchor anchor Anchor center
+ itk_option define -borderwidth borderWidth BorderWidth 2
+ itk_option define \
+ -disabledforeground disabledForeground DisabledForeground #a3a3a3
+ itk_option define \
+ -font font Font "-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*"
+ itk_option define \
+ -highlightbackground highlightBackground HighlightBackground #d9d9d9
+ itk_option define -highlightcolor highlightColor HighlightColor Black
+ itk_option define \
+ -highlightthickness highlightThickness HighlightThickness 0
+ itk_option define -justify justify Justify center
+ itk_option define -padx padX Pad 4p
+ itk_option define -pady padY Pad 3p
+ itk_option define -wraplength wrapLength WrapLength 0
+ itk_option define -menubuttons menuButtons MenuButtons {}
+ itk_option define -helpvariable helpVariable HelpVariable {}
+
+ public {
+ method add { type path args } { }
+ method delete { args } { }
+ method index { path } { }
+ method insert { beforeComponent type name args }
+ method invoke { entryPath } { }
+ method menucget { args } { }
+ method menuconfigure { path args } { }
+ method path { args } { }
+ method type { path } { }
+ method yposition { entryPath } { }
+ }
+
+ private {
+ method menubutton { menuName args } { }
+ method options { args } { }
+ method command { cmdName args } { }
+ method checkbutton { chkName args } { }
+ method radiobutton { radName args } { }
+ method separator { sepName args } { }
+ method cascade { casName args } { }
+ method _helpHandler { menuPath } { }
+ method _addMenuButton { buttonName args} { }
+ method _insertMenuButton { beforeMenuPath buttonName args} { }
+ method _makeMenuButton {buttonName args} { }
+ method _makeMenu \
+ { componentName widgetName menuPath menuEvalStr } { }
+ method _substEvalStr { evalStr } { }
+ method _deleteMenu { menuPath {menuPath2 {}} } { }
+ method _deleteAMenu { path } { }
+ method _addEntry { type path args } { }
+ method _addCascade { tkMenuPath path args } { }
+ method _insertEntry { beforeEntryPath type name args } { }
+ method _insertCascade { bfIndex tkMenuPath path args } { }
+ method _deleteEntry { entryPath {entryPath2 {}} } { }
+ method _configureMenu { path tkPath {option {}} args } { }
+ method _configureMenuOption { type path args } { }
+ method _configureMenuEntry { path index {option {}} args } { }
+ method _unsetPaths { parent } { }
+ method _entryPathToTkMenuPath {entryPath} { }
+ method _getTkIndex { tkMenuPath tkIndex} { }
+ method _getPdIndex { tkMenuPath tkIndex } { }
+ method _getMenuList { } { }
+ method _getEntryList { menu } { }
+ method _parsePath { path } { }
+ method _getSymbolicPath { parent segment } { }
+ method _getCallerLevel { }
+
+ variable _parseLevel 0 ;# The parse level depth
+ variable _callerLevel #0 ;# abs level of caller
+ variable _pathMap ;# Array indexed by Menubar's path
+ ;# naming, yields tk menu path
+ variable _entryIndex -1 ;# current entry help is displayed
+ ;# for during help <motion> events
+
+ variable _tkMenuPath ;# last tk menu being added to
+ variable _ourMenuPath ;# our last valid path constructed.
+
+ variable _menuOption ;# The -menu option
+ variable _helpString ;# The -helpstr optio
+ }
+}
+
+#
+# Use option database to override default resources.
+#
+option add *Menubar*Menu*tearOff false widgetDefault
+option add *Menubar*Menubutton*relief flat widgetDefault
+option add *Menubar*Menu*relief raised widgetDefault
+
+#
+# Provide a lowercase access method for the menubar class
+#
+proc ::iwidgets::menubar { args } {
+ uplevel ::iwidgets::Menubar $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Menubar::constructor { args } {
+ component hull configure -borderwidth 0
+
+ #
+ # Create the Menubar Frame that will hold the menus.
+ #
+ # might want to make -relief and -bd options with defaults
+ itk_component add menubar {
+ frame $itk_interior.menubar -relief raised -bd 2
+ } {
+ keep -cursor -background -width -height
+ }
+ pack $itk_component(menubar) -fill both -expand yes
+
+ # Map our pathname to class to the actual menubar frame
+ set _pathMap(.) $itk_component(menubar)
+
+ eval itk_initialize $args
+
+ #
+ # HACK HACK HACK
+ # Tk expects some variables to be defined and due to some
+ # unknown reason we confuse its normal ordering. So, if
+ # the user creates a menubutton with no menu it will fail
+ # when clicked on with a "Error: can't read $tkPriv(oldGrab):
+ # no such element in array". So by setting it to null we
+ # avoid this error.
+ uplevel #0 "set tkPriv(oldGrab) {}"
+
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+# This first set of options are for configuring menus and/or menubuttons
+# at the menu level.
+#
+# ------------------------------------------------------------------
+# OPTION -foreground
+#
+# menu
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::foreground {
+}
+
+# ------------------------------------------------------------------
+# OPTION -activebackground
+#
+# menu
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::activebackground {
+}
+
+# ------------------------------------------------------------------
+# OPTION -activeborderwidth
+#
+# menu
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::activeborderwidth {
+}
+
+# ------------------------------------------------------------------
+# OPTION -activeforeground
+#
+# menu
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::activeforeground {
+}
+
+# ------------------------------------------------------------------
+# OPTION -anchor
+#
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::anchor {
+}
+
+# ------------------------------------------------------------------
+# OPTION -borderwidth
+#
+# menu
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::borderwidth {
+}
+
+# ------------------------------------------------------------------
+# OPTION -disabledforeground
+#
+# menu
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::disabledforeground {
+}
+
+# ------------------------------------------------------------------
+# OPTION -font
+#
+# menu
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::font {
+}
+
+# ------------------------------------------------------------------
+# OPTION -highlightbackground
+#
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::highlightbackground {
+}
+
+# ------------------------------------------------------------------
+# OPTION -highlightcolor
+#
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::highlightcolor {
+}
+
+# ------------------------------------------------------------------
+# OPTION -highlightthickness
+#
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::highlightthickness {
+}
+
+# ------------------------------------------------------------------
+# OPTION -justify
+#
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::justify {
+}
+
+# ------------------------------------------------------------------
+# OPTION -padx
+#
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::padx {
+}
+
+# ------------------------------------------------------------------
+# OPTION -pady
+#
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::pady {
+}
+
+# ------------------------------------------------------------------
+# OPTION -wraplength
+#
+# menubutton
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::wraplength {
+}
+
+# ------------------------------------------------------------------
+# OPTION -menubuttons
+#
+# The menuButton option is a string which specifies the arrangement
+# of menubuttons on the Menubar frame. Each menubutton entry is
+# delimited by the newline character. Each entry is treated as
+# an add command to the Menubar.
+#
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::menubuttons {
+ if { $itk_option(-menubuttons) != {} } {
+
+ # IF one exists already, delete the old one and create
+ # a new one
+ if { ! [catch {_parsePath .0}] } {
+ delete .0 .last
+ }
+
+ #
+ # Determine the context level to evaluate the option string at
+ #
+ set _callerLevel [_getCallerLevel]
+
+ #
+ # Parse the option string in their scope, then execute it in
+ # our scope.
+ #
+ incr _parseLevel
+ _substEvalStr itk_option(-menubuttons)
+ eval $itk_option(-menubuttons)
+
+ # reset so that we know we aren't parsing in a scope currently.
+ incr _parseLevel -1
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION -helpvariable
+#
+# Specifies the global variable to update whenever the mouse is in
+# motion over a menu entry. This global variable is updated with the
+# current value of the active menu entry's helpStr. Other widgets
+# can "watch" this variable with the trace command, or as is the
+# case with entry or label widgets, they can set their textVariable
+# to the same global variable. This allows for a simple implementation
+# of a help status bar. Whenever the mouse leaves a menu entry,
+# the helpVariable is set to the empty string {}.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Menubar::helpvariable {
+ if {"" != $itk_option(-helpvariable) &&
+ ![string match ::* $itk_option(-helpvariable)] &&
+ ![string match @itcl* $itk_option(-helpvariable)]} {
+ set itk_option(-helpvariable) "::$itk_option(-helpvariable)"
+ }
+}
+
+
+# -------------------------------------------------------------
+#
+# METHOD: add type path args
+#
+# Adds either a menu to the menu bar or a menu entry to a
+# menu pane.
+#
+# If the type is one of cascade, checkbutton, command,
+# radiobutton, or separator it adds a new entry to the bottom
+# of the menu denoted by the menuPath prefix of componentPath-
+# Name. The new entry's type is given by type. If additional
+# arguments are present, they specify options available to
+# component type Entry. See the man pages for menu(n) in the
+# section on Entries. In addition all entries accept an added
+# option, helpStr:
+#
+# -helpstr value
+#
+# Specifes the string to associate with the entry.
+# When the mouse moves over the associated entry, the variable
+# denoted by helpVariable is set. Another widget can bind to
+# the helpVariable and thus display status help.
+#
+# If the type is menubutton, it adds a new menubut-
+# ton to the menu bar. If additional arguments are present,
+# they specify options available to component type MenuButton.
+#
+# If the type is menubutton or cascade, the menu
+# option is available in addition to normal Tk options for
+# these to types.
+#
+# -menu menuSpec
+#
+# This is only valid for componentPathNames of type
+# menubutton or cascade. Specifes an option set and/or a set
+# of entries to place on a menu and associate with the menu-
+# button or cascade. The option keyword allows the menu widget
+# to be configured. Each item in the menuSpec is treated as
+# add commands (each with the possibility of having other
+# -menu options). In this way a menu can be recursively built.
+#
+# The last segment of componentPathName cannot be
+# one of the keywords last, menu, end. Additionally, it may
+# not be a number. However the componentPathName may be refer-
+# enced in this manner (see discussion of Component Path
+# Names).
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::add { type path args } {
+ if ![regexp \
+ {^(menubutton|command|cascade|separator|radiobutton|checkbutton)$} \
+ $type] {
+ error "bad type \"$type\": must be one of the following:\
+ \"command\", \"checkbutton\", \"radiobutton\",\
+ \"separator\", \"cascade\", or \"menubutton\""
+ }
+ regexp {[^.]+$} $path segName
+ if [regexp {^(menu|last|end|[0-9]+)$} $segName] {
+ error "bad name \"$segName\": user created component \
+ path names may not end with \
+ \"end\", \"last\", \"menu\", \
+ or be an integer"
+ }
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # OK, either add a menu
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ if { $type == "menubutton" } {
+ # grab the last component name (the menu name)
+ eval _addMenuButton $segName $args
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Or add an entry
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ } else {
+ eval _addEntry $type $path $args
+ }
+}
+
+
+# -------------------------------------------------------------
+#
+# METHOD: delete entryPath ?entryPath2?
+#
+# If componentPathName is of component type MenuButton or
+# Menu, delete operates on menus. If componentPathName is of
+# component type Entry, delete operates on menu entries.
+#
+# This command deletes all components between com-
+# ponentPathName and componentPathName2 inclusive. If com-
+# ponentPathName2 is omitted then it defaults to com-
+# ponentPathName. Returns an empty string.
+#
+# If componentPathName is of type Menubar, then all menus
+# and the menu bar frame will be destroyed. In this case com-
+# ponentPathName2 is ignored.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::delete { args } {
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Handle out of bounds in arg lengths
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ if { [llength $args] > 0 && [llength $args] <=2 } {
+
+ # Path Conversions
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ set path [_parsePath [lindex $args 0]]
+
+ set pathOrIndex $_pathMap($path)
+
+ # Menu Entry
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ if { [regexp {^[0-9]+$} $pathOrIndex] } {
+ eval "_deleteEntry $args"
+
+ # Menu
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ } else {
+ eval "_deleteMenu $args"
+ }
+ } else {
+ error "wrong # args: should be \
+ \"$itk_component(hull) delete pathName ?pathName2?\""
+ }
+ return ""
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: index path
+#
+# If componentPathName is of type menubutton or menu, it
+# returns the position of the menu/menubutton on the Menubar
+# frame.
+#
+# If componentPathName is of type command, separator,
+# radiobutton, checkbutton, or cascade, it returns the menu
+# widget's numerical index for the entry corresponding to com-
+# ponentPathName. If path is not found or the Menubar frame is
+# passed in, -1 is returned.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::index { path } {
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Path conversions
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ if { [catch {set fullPath [_parsePath $path]} ] } {
+ return -1
+ }
+ if { [catch {set tkPathOrIndex $_pathMap($fullPath)} ] } {
+ return -1
+ }
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # If integer, return the value, otherwise look up the menu position
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ if { [regexp {^[0-9]+$} $tkPathOrIndex] } {
+ set index $tkPathOrIndex
+ } else {
+ set index [lsearch [_getMenuList] $fullPath]
+ }
+
+ return $index
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: insert beforeComponent type name ?option value?
+#
+# Insert a new component named name before the component
+# specified by componentPathName.
+#
+# If componentPathName is of type MenuButton or Menu, the
+# new component inserted is of type Menu and given the name
+# name. In this case valid option value pairs are those
+# accepted by menubuttons.
+#
+# If componentPathName is of type Entry, the new com-
+# ponent inserted is of type Entry and given the name name. In
+# this case valid option value pairs are those accepted by
+# menu entries.
+#
+# name cannot be one of the keywords last, menu, end.
+# dditionally, it may not be a number. However the com-
+# ponentPathName may be referenced in this manner (see discus-
+# sion of Component Path Names).
+#
+# Returns -1 if the menubar frame is passed in.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::insert { beforeComponent type name args } {
+ if ![regexp \
+ {^(menubutton|command|cascade|separator|radiobutton|checkbutton)$} \
+ $type] {
+ error "bad type \"$type\": must be one of the following:\
+ \"command\", \"checkbutton\", \"radiobutton\",\
+ \"separator\", \"cascade\", or \"menubutton\""
+ }
+ regexp {[^.]+$} $name segName
+ if [regexp {^(menu|last|end|[0-9]+)$} $segName] {
+ error "bad name \"$name\": user created component \
+ path names may not end with \
+ \"end\", \"last\", \"menu\", \
+ or be an integer"
+ }
+
+ set beforeComponent [_parsePath $beforeComponent]
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Choose menu insertion or entry insertion
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ if { $type == "menubutton" } {
+ eval _insertMenuButton $beforeComponent $name $args
+ } else {
+ eval _insertEntry $beforeComponent $type $name $args
+ }
+}
+
+
+# -------------------------------------------------------------
+#
+# METHOD: invoke entryPath
+#
+# Invoke the action of the menu entry denoted by
+# entryComponentPathName. See the sections on the individual
+# entries in the menu(n) man pages. If the menu entry is dis-
+# abled then nothing happens. If the entry has a command
+# associated with it then the result of that command is
+# returned as the result of the invoke widget command. Other-
+# wise the result is an empty string.
+#
+# If componentPathName is not a menu entry, an error is
+# issued.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::invoke { entryPath } {
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Path Conversions
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ set entryPath [_parsePath $entryPath]
+ set index $_pathMap($entryPath)
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Error Processing
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ # first verify that beforeEntryPath is actually a path to
+ # an entry and not to menu, menubutton, etc.
+ if { ! [regexp {^[0-9]+$} $index] } {
+ error "bad entry path: beforeEntryPath is not an entry"
+ }
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Call invoke command
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ # get the tk menu path to call
+ set tkMenuPath [_entryPathToTkMenuPath $entryPath]
+
+ # call the menu's invoke command, adjusting index based on tearoff
+ $tkMenuPath invoke [_getTkIndex $tkMenuPath $index]
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: menucget componentPath option
+#
+# Returns the current value of the configuration option
+# given by option. The component type of componentPathName
+# determines the valid available options.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::menucget { path opt } {
+ return [lindex [menuconfigure $path $opt] 4]
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: menuconfigure componentPath ?option? ?value option value...?
+#
+# Query or modify the configuration options of the sub-
+# component of the Menubar specified by componentPathName. If
+# no option is specified, returns a list describing all of the
+# available options for componentPathName (see
+# Tk_ConfigureInfo for information on the format of this
+# list). If option is specified with no value, then the com-
+# mand returns a list describing the one named option (this
+# list will be identical to the corresponding sublist of the
+# value returned if no option is specified). If one or more
+# option-value pairs are specified, then the command modifies
+# the given widget option(s) to have the given value(s); in
+# this case the command returns an empty string. The component
+# type of componentPathName determines the valid available
+# options.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::menuconfigure { path args } {
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Path Conversions
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ set path [_parsePath $path]
+ set tkPathOrIndex $_pathMap($path)
+
+ # Case: Menu entry being configured
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ if { [regexp {^[0-9]+$} $tkPathOrIndex] } {
+ eval "_configureMenuEntry $path $tkPathOrIndex $args"
+
+ # Case: Menu (button and pane) being configured.
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ } else {
+ eval _configureMenu $path $tkPathOrIndex $args
+ }
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: path
+#
+# SYNOPIS: path ?<mode>? <pattern>
+#
+# Returns a fully formed component path that matches pat-
+# tern. If no match is found it returns -1. The mode argument
+# indicates how the search is to be matched against pattern
+# and it must have one of the following values:
+#
+# -glob Pattern is a glob-style pattern which is
+# matched against each component path using the same rules as
+# the string match command.
+#
+# -regexp Pattern is treated as a regular expression
+# and matched against each component path using the same
+# rules as the regexp command.
+#
+# The default mode is -glob.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::path { args } {
+
+ set len [llength $args]
+ if { $len < 1 || $len > 2 } {
+ error "wrong # args: should be \
+ \"$itk_component(hull) path ?mode?> <pattern>\""
+ }
+
+ set pathList [array names _pathMap]
+
+ set len [llength $args]
+ switch -- $len {
+ 1 {
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Case: no search modes given
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ set pattern [lindex $args 0]
+ set found [lindex $pathList [lsearch -glob $pathList $pattern]]
+ }
+ 2 {
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Case: search modes present (-glob, -regexp)
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ set options [lindex $args 0]
+ set pattern [lindex $args 1]
+ set found \
+ [lindex $pathList [lsearch $options $pathList $pattern]]
+ }
+ default {
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Case: wrong # arguments
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ error "wrong # args: \
+ should be \"$itk_component(hull) path ?-glob? ?-regexp? pattern\""
+ }
+ }
+
+ return $found
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: type path
+#
+# Returns the type of the component given by entryCom-
+# ponentPathName. For menu entries, this is the type argument
+# passed to the add/insert widget command when the entry was
+# created, such as command or separator. Othewise it is either
+# a menubutton or a menu.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::type { path } {
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Path Conversions
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ set path [_parsePath $path]
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Error Handling: does the path exist?
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ if { [catch {set index $_pathMap($path)} ] } {
+ error "bad path \"$path\""
+ }
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # ENTRY, Ask TK for type
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ if { [regexp {^[0-9]+$} $index] } {
+ # get the menu path from the entry path name
+ set tkMenuPath [_entryPathToTkMenuPath $path]
+
+ # call the menu's type command, adjusting index based on tearoff
+ set type [$tkMenuPath type [_getTkIndex $tkMenuPath $index]]
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # MENUBUTTON, MENU, or FRAME
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ } else {
+ # should not happen, but have a path that is not a valid window.
+ if { [catch {set className [winfo class $_pathMap($path)]}] } {
+ error "serious error: \"$path\" is not a valid window"
+ }
+ # get the classname, look it up, get index, us it to look up type
+ set type [ lindex \
+ {frame menubutton menu} \
+ [lsearch { Frame Menubutton Menu } $className] \
+ ]
+ }
+ return $type
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: yposition entryPath
+#
+# Returns a decimal string giving the y-coordinate within
+# the menu window of the topmost pixel in the entry specified
+# by componentPathName. If the componentPathName is not an
+# entry, an error is issued.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::yposition { entryPath } {
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Path Conversions
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ set entryPath [_parsePath $entryPath]
+ set index $_pathMap($entryPath)
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Error Handling
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ # first verify that entryPath is actually a path to
+ # an entry and not to menu, menubutton, etc.
+ if { ! [regexp {^[0-9]+$} $index] } {
+ error "bad value: entryPath is not an entry"
+ }
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Call yposition command
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+ # get the menu path from the entry path name
+ set tkMenuPath [_entryPathToTkMenuPath $entryPath]
+
+ # call the menu's yposition command, adjusting index based on tearoff
+ return [$tkMenuPath yposition [_getTkIndex $tkMenuPath $index]]
+
+}
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# PARSING METHODS
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# -------------------------------------------------------------
+#
+# PARSING METHOD: menubutton
+#
+# This method is invoked via an evaluation of the -menubuttons
+# option for the Menubar.
+#
+# It adds a new menubutton and processes any -menu options
+# for creating entries on the menu pane associated with the
+# menubutton
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::menubutton { menuName args } {
+ eval "add menubutton .$menuName $args"
+}
+
+# -------------------------------------------------------------
+#
+# PARSING METHOD: options
+#
+# This method is invoked via an evaluation of the -menu
+# option for menubutton commands.
+#
+# It configures the current menu ($_ourMenuPath) with the options
+# that follow (args)
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::options { args } {
+ eval "$_tkMenuPath configure $args"
+}
+
+
+# -------------------------------------------------------------
+#
+# PARSING METHOD: command
+#
+# This method is invoked via an evaluation of the -menu
+# option for menubutton commands.
+#
+# It adds a new command entry to the current menu, $_ourMenuPath
+# naming it $cmdName. Since this is the most common case when
+# creating menus, streamline it by duplicating some code from
+# the add{} method.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::command { cmdName args } {
+ set path $_ourMenuPath.$cmdName
+
+ # error checking
+ regsub {.*[.]} $path "" segName
+ if [regexp {^(menu|last|end|[0-9]+)$} $segName] {
+ error "bad name \"$segName\": user created component \
+ path names may not end with \
+ \"end\", \"last\", \"menu\", \
+ or be an integer"
+ }
+
+ eval _addEntry command $path $args
+}
+
+# -------------------------------------------------------------
+#
+# PARSING METHOD: checkbutton
+#
+# This method is invoked via an evaluation of the -menu
+# option for menubutton/cascade commands.
+#
+# It adds a new checkbutton entry to the current menu, $_ourMenuPath
+# naming it $chkName.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::checkbutton { chkName args } {
+ eval "add checkbutton $_ourMenuPath.$chkName $args"
+}
+
+# -------------------------------------------------------------
+#
+# PARSING METHOD: radiobutton
+#
+# This method is invoked via an evaluation of the -menu
+# option for menubutton/cascade commands.
+#
+# It adds a new radiobutton entry to the current menu, $_ourMenuPath
+# naming it $radName.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::radiobutton { radName args } {
+ eval "add radiobutton $_ourMenuPath.$radName $args"
+}
+
+# -------------------------------------------------------------
+#
+# PARSING METHOD: separator
+#
+# This method is invoked via an evaluation of the -menu
+# option for menubutton/cascade commands.
+#
+# It adds a new separator entry to the current menu, $_ourMenuPath
+# naming it $sepName.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::separator { sepName args } {
+ eval $_tkMenuPath add separator
+ set _pathMap($_ourMenuPath.$sepName) [_getPdIndex $_tkMenuPath end]
+}
+
+# -------------------------------------------------------------
+#
+# PARSING METHOD: cascade
+#
+# This method is invoked via an evaluation of the -menu
+# option for menubutton/cascade commands.
+#
+# It adds a new cascade entry to the current menu, $_ourMenuPath
+# naming it $casName. It processes the -menu option if present,
+# adding a new menu pane and its associated entries found.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::cascade { casName args } {
+
+ # Save the current menu we are adding to, cascade can change
+ # the current menu through -menu options.
+ set saveOMP $_ourMenuPath
+ set saveTKP $_tkMenuPath
+
+ eval "add cascade $_ourMenuPath.$casName $args"
+
+ # Restore the saved menu states so that the next entries of
+ # the -menu/-menubuttons we are processing will be at correct level.
+ set _ourMenuPath $saveOMP
+ set _tkMenuPath $saveTKP
+}
+
+# ... A P I S U P P O R T M E T H O D S...
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# MENU ADD, INSERT, DELETE
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _addMenuButton
+#
+# Makes a new menubutton & associated -menu, pack appended
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_addMenuButton { buttonName args} {
+
+ eval "_makeMenuButton $buttonName $args"
+
+ #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Pack at end, adjust for help buttonName
+ # ''''''''''''''''''''''''''''''''''
+ if { $buttonName == "help" } {
+ pack $itk_component($buttonName) -side right
+ } else {
+ pack $itk_component($buttonName) -side left
+ }
+
+ return $itk_component($buttonName)
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _insertMenuButton
+#
+# inserts a menubutton named $buttonName on a menu bar before
+# another menubutton specified by $beforeMenuPath
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_insertMenuButton { beforeMenuPath buttonName args} {
+
+ eval "_makeMenuButton $buttonName $args"
+
+ #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Pack before the $beforeMenuPath
+ # ''''''''''''''''''''''''''''''''
+ set beforeTkMenu $_pathMap($beforeMenuPath)
+ regsub {[.]menu$} $beforeTkMenu "" beforeTkMenu
+ pack $itk_component(menubar).$buttonName \
+ -side left \
+ -before $beforeTkMenu
+
+ return $itk_component($buttonName)
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _makeMenuButton
+#
+# creates a menubutton named buttonName on the menubar with args.
+# The -menu option if present will trigger attaching a menu pane.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_makeMenuButton {buttonName args} {
+
+ #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Capture the -menu option if present
+ # '''''''''''''''''''''''''''''''''''
+ array set temp $args
+ if { [::info exists temp(-menu)] } {
+ # We only keep this in case of menuconfigure or menucget
+ set _menuOption(.$buttonName) $temp(-menu)
+ set menuEvalStr $temp(-menu)
+ } else {
+ set menuEvalStr {}
+ }
+
+ # attach the actual menu widget to the menubutton's arg list
+ set temp(-menu) $itk_component(menubar).$buttonName.menu
+ set args [array get temp]
+
+ #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Create menubutton component
+ # ''''''''''''''''''''''''''''''''
+ itk_component add $buttonName {
+ eval ::menubutton \
+ $itk_component(menubar).$buttonName \
+ $args
+ } {
+ keep \
+ -activebackground \
+ -activeforeground \
+ -anchor \
+ -background \
+ -borderwidth \
+ -cursor \
+ -disabledforeground \
+ -font \
+ -foreground \
+ -highlightbackground \
+ -highlightcolor \
+ -highlightthickness \
+ -justify \
+ -padx \
+ -pady \
+ -wraplength
+ }
+
+ set _pathMap(.$buttonName) $itk_component($buttonName)
+
+ _makeMenu \
+ $buttonName-menu \
+ $itk_component($buttonName).menu \
+ .$buttonName \
+ $menuEvalStr
+
+ return $itk_component($buttonName)
+
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _makeMenu
+#
+# Creates a menu.
+# It then evaluates the $menuEvalStr to create entries on the menu.
+#
+# Assumes the existence of $itk_component($buttonName)
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_makeMenu \
+ { componentName widgetName menuPath menuEvalStr } {
+
+ #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Create menu component
+ # ''''''''''''''''''''''''''''''''
+ itk_component add $componentName {
+ ::menu $widgetName
+ } {
+ keep \
+ -activebackground \
+ -activeborderwidth \
+ -activeforeground \
+ -background \
+ -borderwidth \
+ -cursor \
+ -disabledforeground \
+ -font \
+ -foreground
+ }
+
+ set _pathMap($menuPath.menu) $itk_component($componentName)
+
+ #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Attach help handler to this menu
+ # ''''''''''''''''''''''''''''''''
+ bind $itk_component($componentName) <<MenuSelect>> \
+ [itcl::code $this _helpHandler $menuPath.menu]
+
+ #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Handle -menu
+ #'''''''''''''''''''''''''''''''''
+ set _ourMenuPath $menuPath
+ set _tkMenuPath $itk_component($componentName)
+
+ #
+ # A zero parseLevel says we are at the top of the parse tree,
+ # so get the context scope level and do a subst for the menuEvalStr.
+ #
+ if { $_parseLevel == 0 } {
+ set _callerLevel [_getCallerLevel]
+ }
+
+ #
+ # bump up the parse level, so if we get called via the 'eval $menuEvalStr'
+ # we know to skip the above steps...
+ #
+ incr _parseLevel
+ eval $menuEvalStr
+
+ #
+ # leaving, so done with this parse level, so bump it back down
+ #
+ incr _parseLevel -1
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _substEvalStr
+#
+# This performs the substitution and evaluation of $ [], \ found
+# in the -menubutton/-menus options
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_substEvalStr { evalStr } {
+ upvar $evalStr evalStrRef
+ set evalStrRef [uplevel $_callerLevel [list subst $evalStrRef]]
+}
+
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _deleteMenu
+#
+# _deleteMenu menuPath ?menuPath2?
+#
+# deletes menuPath or from menuPath to menuPath2
+#
+# Menu paths may be formed in one of two ways
+# .MENUBAR.menuName where menuName is the name of the menu
+# .MENUBAR.menuName.menu where menuName is the name of the menu
+#
+# The basic rule is '.menu' is not needed.
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_deleteMenu { menuPath {menuPath2 {}} } {
+
+ if { $menuPath2 == "" } {
+ # get a corrected path (subst for number, last, end)
+ set path [_parsePath $menuPath]
+
+ _deleteAMenu $path
+
+ } else {
+ # gets the list of menus in interface order
+ set menuList [_getMenuList]
+
+ # ... get the start menu and the last menu ...
+
+ # get a corrected path (subst for number, last, end)
+ set menuStartPath [_parsePath $menuPath]
+
+ regsub {[.]menu$} $menuStartPath "" menuStartPath
+
+ set menuEndPath [_parsePath $menuPath2]
+
+ regsub {[.]menu$} $menuEndPath "" menuEndPath
+
+ # get the menu position (0 based) of the start and end menus.
+ set start [lsearch -exact $menuList $menuStartPath]
+ if { $start == -1 } {
+ error "bad menu path \"$menuStartPath\": \
+ should be one of $menuList"
+ }
+ set end [lsearch -exact $menuList $menuEndPath]
+ if { $end == -1 } {
+ error "bad menu path \"$menuEndPath\": \
+ should be one of $menuList"
+ }
+
+ # now create the list from this range of menus
+ set delList [lrange $menuList $start $end]
+
+ # walk thru them deleting each menu.
+ # this list has no .menu on the end.
+ foreach m $delList {
+ _deleteAMenu $m.menu
+ }
+ }
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _deleteAMenu
+#
+# _deleteMenu menuPath
+#
+# deletes a single Menu (menubutton and menu pane with entries)
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_deleteAMenu { path } {
+
+ # We will normalize the path to not include the '.menu' if
+ # it is on the path already.
+
+ regsub {[.]menu$} $path "" menuButtonPath
+ regsub {.*[.]} $menuButtonPath "" buttonName
+
+ # Loop through and destroy any cascades, etc on menu.
+ set entryList [_getEntryList $menuButtonPath]
+ foreach entry $entryList {
+ _deleteEntry $entry
+ }
+
+ # Delete the menubutton and menu components...
+ destroy $itk_component($buttonName-menu)
+ destroy $itk_component($buttonName)
+
+ # This is because of some itcl bug that doesn't delete
+ # the component on the destroy in some cases...
+ catch {itk_component delete $buttonName-menu}
+ catch {itk_component delete $buttonName}
+
+ # unset our paths
+ _unsetPaths $menuButtonPath
+
+}
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ENTRY ADD, INSERT, DELETE
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _addEntry
+#
+# Adds an entry to menu.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_addEntry { type path args } {
+
+ # Error Checking
+ # ''''''''''''''
+ # the path should not end with '.menu'
+ # Not needed -- already checked by add{}
+ # if { [regexp {[.]menu$} $path] } {
+ # error "bad entry path: \"$path\". \
+ # The name \"menu\" is reserved for menu panes"
+ # }
+
+ # get the tkMenuPath
+ set tkMenuPath [_entryPathToTkMenuPath $path]
+ if { $tkMenuPath == "" } {
+ error "bad entry path: \"$path\". The menu path prefix is not valid"
+ }
+
+ # get the -helpstr option if present
+ array set temp $args
+ if { [::info exists temp(-helpstr)] } {
+ set helpStr $temp(-helpstr)
+ unset temp(-helpstr)
+ } else {
+ set helpStr {}
+ }
+ set args [array get temp]
+
+ # Handle CASCADE
+ # ''''''''''''''
+ # if this is a cascade go ahead and add in the menu...
+ if { $type == "cascade" } {
+ eval [list _addCascade $tkMenuPath $path] $args
+ # Handle Non-CASCADE
+ # ''''''''''''''''''
+ } else {
+ # add the entry if one doesn't already exist with the same
+ # command name
+ if [::info exists _pathMap($path)] {
+ set cmdname [lindex [split $path .] end]
+ error "Cannot add $type \"$cmdname\". A menu item already\
+ exists with this name."
+ }
+ eval [list $tkMenuPath add $type] $args
+ set _pathMap($path) [_getPdIndex $tkMenuPath end]
+ }
+
+ # Remember the help string
+ set _helpString($path) $helpStr
+
+ return $_pathMap($path)
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _addCascade
+#
+# Creates a cascade button. Handles the -menu option
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_addCascade { tkMenuPath path args } {
+
+ # get the cascade name from our path
+ regsub {.*[.]} $path "" cascadeName
+
+ #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Capture the -menu option if present
+ # '''''''''''''''''''''''''''''''''''
+ array set temp $args
+ if { [::info exists temp(-menu)] } {
+ set menuEvalStr $temp(-menu)
+ } else {
+ set menuEvalStr {}
+ }
+
+ # attach the menu pane
+ set temp(-menu) $tkMenuPath.$cascadeName
+ set args [array get temp]
+
+ # Create the cascade entry
+ eval $tkMenuPath add cascade $args
+
+ # Keep the -menu string in case of menuconfigure or menucget
+ if { $menuEvalStr != "" } {
+ set _menuOption($path) $menuEvalStr
+ }
+
+ # update our pathmap
+ set _pathMap($path) [_getPdIndex $tkMenuPath end]
+
+ _makeMenu \
+ $cascadeName-menu \
+ $tkMenuPath.$cascadeName \
+ $path \
+ $menuEvalStr
+
+ #return $itk_component($cascadeName)
+
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _insertEntry
+#
+# inserts an entry on a menu before entry given by beforeEntryPath.
+# The added entry is of type TYPE and its name is NAME. ARGS are
+# passed for customization of the entry.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_insertEntry { beforeEntryPath type name args } {
+
+ # convert entryPath to an index value
+ set bfIndex $_pathMap($beforeEntryPath)
+
+ # first verify that beforeEntryPath is actually a path to
+ # an entry and not to menu, menubutton, etc.
+ if { ! [regexp {^[0-9]+$} $bfIndex] } {
+ error "bad entry path: $beforeEntryPath is not an entry"
+ }
+
+ # get the menu path from the entry path name
+ regsub {[.][^.]*$} $beforeEntryPath "" menuPathPrefix
+ set tkMenuPath $_pathMap($menuPathPrefix.menu)
+
+ # If this entry already exists in the path map, throw an error.
+ if [::info exists _pathMap($menuPathPrefix.$name)] {
+ error "Cannot insert $type \"$name\". A menu item already\
+ exists with this name."
+ }
+
+ # INDEX is zero based at this point.
+
+ # ENTRIES is a zero based list...
+ set entries [_getEntryList $menuPathPrefix]
+
+ #
+ # Adjust the entries after the inserted item, to have
+ # the correct index numbers. Note, we stay zero based
+ # even though tk flips back and forth depending on tearoffs.
+ #
+ for {set i $bfIndex} {$i < [llength $entries]} {incr i} {
+ # path==entry path in numerical order
+ set path [lindex $entries $i]
+
+ # add one to each entry after the inserted one.
+ set _pathMap($path) [expr {$i + 1}]
+ }
+
+ # get the -helpstr option if present
+ array set temp $args
+ if { [::info exists temp(-helpstr)] } {
+ set helpStr $temp(-helpstr)
+ unset temp(-helpstr)
+ } else {
+ set helpStr {}
+ }
+ set args [array get temp]
+
+ set path $menuPathPrefix.$name
+
+ # Handle CASCADE
+ # ''''''''''''''
+ # if this is a cascade go ahead and add in the menu...
+ if { [string match cascade $type] } {
+
+ if { [ catch {eval "_insertCascade \
+ $bfIndex $tkMenuPath $path $args"} errMsg ]} {
+ for {set i $bfIndex} {$i < [llength $entries]} {incr i} {
+ # path==entry path in numerical order
+ set path [lindex $entries $i]
+
+ # sub the one we added earlier.
+ set _pathMap($path) [expr {$_pathMap($path) - 1}]
+ # @@ delete $hs
+ }
+ error $errMsg
+ }
+
+ # Handle Entry
+ # ''''''''''''''
+ } else {
+
+ # give us a zero or 1-based index based on tear-off menu status
+ # invoke the menu's insert command
+ if { [catch {eval "$tkMenuPath insert \
+ [_getTkIndex $tkMenuPath $bfIndex] $type $args"} errMsg]} {
+ for {set i $bfIndex} {$i < [llength $entries]} {incr i} {
+ # path==entry path in numerical order
+ set path [lindex $entries $i]
+
+ # sub the one we added earlier.
+ set _pathMap($path) [expr {$_pathMap($path) - 1}]
+ # @@ delete $hs
+ }
+ error $errMsg
+ }
+
+
+ # add the helpstr option to our options list (attach to entry)
+ set _helpString($path) $helpStr
+
+ # Insert the new entry path into pathmap giving it an index value
+ set _pathMap($menuPathPrefix.$name) $bfIndex
+
+ }
+
+ return [_getTkIndex $tkMenuPath $bfIndex]
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _insertCascade
+#
+# Creates a cascade button. Handles the -menu option
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_insertCascade { bfIndex tkMenuPath path args } {
+
+ # get the cascade name from our path
+ regsub {.*[.]} $path "" cascadeName
+
+ #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Capture the -menu option if present
+ # '''''''''''''''''''''''''''''''''''
+ array set temp $args
+ if { [::info exists temp(-menu)] } {
+ # Keep the -menu string in case of menuconfigure or menucget
+ set _menuOption($path) $temp(-menu)
+ set menuEvalStr $temp(-menu)
+ } else {
+ set menuEvalStr {}
+ }
+
+ # attach the menu pane
+ set temp(-menu) $tkMenuPath.$cascadeName
+ set args [array get temp]
+
+ # give us a zero or 1-based index based on tear-off menu status
+ # invoke the menu's insert command
+ eval "$tkMenuPath insert \
+ [_getTkIndex $tkMenuPath $bfIndex] cascade $args"
+
+ # Insert the new entry path into pathmap giving it an index value
+ set _pathMap($path) $bfIndex
+ _makeMenu \
+ $cascadeName-menu \
+ $tkMenuPath.$cascadeName \
+ $path \
+ $menuEvalStr
+
+ #return $itk_component($cascadeName)
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _deleteEntry
+#
+# _deleteEntry entryPath ?entryPath2?
+#
+# either
+# deletes the entry entryPath
+# or
+# deletes the entries from entryPath to entryPath2
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_deleteEntry { entryPath {entryPath2 {}} } {
+
+ if { $entryPath2 == "" } {
+ # get a corrected path (subst for number, last, end)
+ set path [_parsePath $entryPath]
+
+ set entryIndex $_pathMap($path)
+ if { $entryIndex == -1 } {
+ error "bad value for pathName: \
+ $entryPath in call to delet"
+ }
+
+ # get the type, if cascade, we will want to delete menu
+ set type [type $path]
+
+ # ... munge up the menu name ...
+
+ # the tkMenuPath is looked up with the .menu added to lookup
+ # strip off the entry component
+ regsub {[.][^.]*$} $path "" menuPath
+ set tkMenuPath $_pathMap($menuPath.menu)
+
+ # get the ordered entry list
+ set entries [_getEntryList $menuPath]
+
+ # ... Fix up path entry indices ...
+
+ # delete the path from the map
+ unset _pathMap([lindex $entries $entryIndex])
+
+ # Subtract off 1 for each entry below the deleted one.
+ for {set i [expr {$entryIndex + 1}]} \
+ {$i < [llength $entries]} \
+ {incr i} {
+ set epath [lindex $entries $i]
+ incr _pathMap($epath) -1
+ }
+
+ # ... Delete the menu entry widget ...
+
+ # delete the menu entry, ajusting index for TK
+ $tkMenuPath delete [_getTkIndex $tkMenuPath $entryIndex]
+
+ if { $type == "cascade" } {
+ regsub {.*[.]} $path "" cascadeName
+ destroy $itk_component($cascadeName-menu)
+
+ # This is because of some itcl bug that doesn't delete
+ # the component on the destroy in some cases...
+ catch {itk_component delete $cascadeName-menu}
+
+ _unsetPaths $path
+ }
+
+ } else {
+ # get a corrected path (subst for number, last, end)
+ set path1 [_parsePath $entryPath]
+ set path2 [_parsePath $entryPath2]
+
+ set fromEntryIndex $_pathMap($path1)
+ if { $fromEntryIndex == -1 } {
+ error "bad value for entryPath1: \
+ $entryPath in call to delet"
+ }
+ set toEntryIndex $_pathMap($path2)
+ if { $toEntryIndex == -1 } {
+ error "bad value for entryPath2: \
+ $entryPath2 in call to delet"
+ }
+ # ... munge up the menu name ...
+
+ # the tkMenuPath is looked up with the .menu added to lookup
+ # strip off the entry component
+ regsub {[.][^.]*$} $path1 "" menuPath
+ set tkMenuPath $_pathMap($menuPath.menu)
+
+ # get the ordered entry list
+ set entries [_getEntryList $menuPath]
+
+ # ... Fix up path entry indices ...
+
+ # delete the range from the pathMap list
+ for {set i $fromEntryIndex} {$i <= $toEntryIndex} {incr i} {
+ unset _pathMap([lindex $entries $i])
+ }
+
+ # Subtract off 1 for each entry below the deleted range.
+ # Loop from one below the bottom delete entry to end list
+ for {set i [expr {$toEntryIndex + 1}]} \
+ {$i < [llength $entries]} \
+ {incr i} {
+ # take this path and sets its index back by size of
+ # deleted range.
+ set path [lindex $entries $i]
+ set _pathMap($path) \
+ [expr {$_pathMap($path) - \
+ (($toEntryIndex - $fromEntryIndex) + 1)}]
+ }
+
+ # ... Delete the menu entry widget ...
+
+ # delete the menu entry, ajusting index for TK
+ $tkMenuPath delete \
+ [_getTkIndex $tkMenuPath $fromEntryIndex] \
+ [_getTkIndex $tkMenuPath $toEntryIndex]
+
+ }
+}
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# CONFIGURATION SUPPORT
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _configureMenu
+#
+# This configures a menu. A menu is a true tk widget, thus we
+# pass the tkPath variable. This path may point to either a
+# menu button (does not end with the name 'menu', or a menu
+# which ends with the name 'menu'
+#
+# path : our Menubar path name to this menu button or menu pane.
+# if we end with the name '.menu' then it is a menu pane.
+# tkPath : the path to the corresponding Tk menubutton or menu.
+# args : the args for configuration
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_configureMenu { path tkPath {option {}} args } {
+
+ set class [winfo class $tkPath]
+
+ if { $option == "" } {
+ # No arguments: return all options
+ set configList [$tkPath configure]
+
+ if { [info exists _menuOption($path)] } {
+ lappend configList [list -menu menu Menu {} $_menuOption($path)]
+ } else {
+ lappend configList [list -menu menu Menu {} {}]
+ }
+ if { [info exists _helpString($path)] } {
+ lappend configList [list -helpstr helpStr HelpStr {} \
+ $_helpString($path)]
+ } else {
+ lappend configList [list -helpstr helpStr HelpStr {} {}]
+ }
+ return $configList
+
+ } elseif {$args == "" } {
+ if { $option == "-menu" } {
+ if { [info exists _menuOption($path)] } {
+ return [list -menu menu Menu {} $_menuOption($path)]
+ } else {
+ return [list -menu menu Menu {} {}]
+ }
+ } elseif { $option == "-helpstr" } {
+ if { [info exists _helpString($path)] } {
+ return [list -helpstr helpStr HelpStr {} $_helpString($path)]
+ } else {
+ return [list -helpstr helpStr HelpStr {} {}]
+ }
+ } else {
+ # ... OTHERWISE, let Tk get it.
+ return [$tkPath configure $option]
+ }
+ } else {
+ set args [concat $option $args]
+
+ # If this is a menubutton, and has -menu option, process it
+ if { $class == "Menubutton" && [regexp -- {-menu} $args] } {
+ eval _configureMenuOption menubutton $path $args
+ } else {
+ eval $tkPath configure $args
+ }
+ return ""
+ }
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _configureMenuOption
+#
+# Allows for configuration of the -menu option on
+# menubuttons and cascades
+#
+# find out if we are the last menu, or are before one.
+# delete the old menu.
+# if we are the last, then add us back at the end
+# if we are before another menu, get the beforePath
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_configureMenuOption { type path args } {
+
+ regsub {[.][^.]*$} $path "" pathPrefix
+
+ if { $type == "menubutton" } {
+ set menuList [_getMenuList]
+ set pos [lsearch $menuList $path]
+ if { $pos == ([llength $menuList] - 1) } {
+ set insert false
+ } else {
+ set insert true
+ }
+ } elseif { $type == "cascade" } {
+ set lastEntryPath [_parsePath $pathPrefix.last]
+ if { $lastEntryPath == $path } {
+ set insert false
+ } else {
+ set insert true
+ }
+ set pos [index $path]
+
+ }
+
+
+ eval "delete $pathPrefix.$pos"
+ if { $insert } {
+ # get name from path...
+ regsub {.*[.]} $path "" name
+
+ eval insert $pathPrefix.$pos $type \
+ $name $args
+ } else {
+ eval add $type $path $args
+ }
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _configureMenuEntry
+#
+# This configures a menu entry. A menu entry is either a command,
+# radiobutton, separator, checkbutton, or a cascade. These have
+# a corresponding Tk index value for the corresponding tk menu
+# path.
+#
+# path : our Menubar path name to this menu entry.
+# index : the t
+# args : the args for configuration
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_configureMenuEntry { path index {option {}} args } {
+
+ set type [type $path]
+
+ # set len [llength $args]
+
+ # get the menu path from the entry path name
+ set tkMenuPath [_entryPathToTkMenuPath $path]
+
+ if { $option == "" } {
+ set configList [$tkMenuPath entryconfigure \
+ [_getTkIndex $tkMenuPath $index]]
+
+ if { $type == "cascade" } {
+ if { [info exists _menuOption($path)] } {
+ lappend configList [list -menu menu Menu {} \
+ $_menuOption($path)]
+ } else {
+ lappend configList [list -menu menu Menu {} {}]
+ }
+ }
+ if { [info exists _helpString($path)] } {
+ lappend configList [list -helpstr helpStr HelpStr {} \
+ $_helpString($path)]
+ } else {
+ lappend configList [list -helpstr helpStr HelpStr {} {}]
+ }
+ return $configList
+
+ } elseif { $args == "" } {
+ if { $option == "-menu" } {
+ if { [info exists _menuOption($path)] } {
+ return [list -menu menu Menu {} $_menuOption($path)]
+ } else {
+ return [list -menu menu Menu {} {}]
+ }
+ } elseif { $option == "-helpstr" } {
+ if { [info exists _helpString($path)] } {
+ return [list -helpstr helpStr HelpStr {} \
+ $_helpString($path)]
+ } else {
+ return [list -helpstr helpStr HelpStr {} {}]
+ }
+ } else {
+ # ... OTHERWISE, let Tk get it.
+ return [$tkMenuPath entryconfigure \
+ [_getTkIndex $tkMenuPath $index] $option]
+ }
+ } else {
+ array set temp [concat $option $args]
+
+ # ... Store -helpstr val,strip out -helpstr val from args
+ if { [::info exists temp(-helpstr)] } {
+ set _helpString($path) $temp(-helpstr)
+ unset temp(-helpstr)
+ }
+
+ set args [array get temp]
+ if { $type == "cascade" && [::info exists temp(-menu)] } {
+ eval "_configureMenuOption cascade $path $args"
+ } else {
+ # invoke the menu's entryconfigure command
+ # being careful to ajust the INDEX to be 0 or 1 based
+ # depending on the tearoff status
+ # if the stripping process brought us down to no options
+ # to set, then forget the configure of widget.
+ if { [llength $args] != 0 } {
+ eval $tkMenuPath entryconfigure \
+ [_getTkIndex $tkMenuPath $index] $args
+ }
+ }
+ return ""
+ }
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _unsetPaths
+#
+# comment
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_unsetPaths { parent } {
+
+ # first get the complete list of all menu paths
+ set pathList [array names _pathMap]
+
+ # for each path that matches parent prefix, unset it.
+ foreach path $pathList {
+ if { [regexp [subst -nocommands {^$parent}] $path] } {
+ unset _pathMap($path)
+ }
+ }
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _entryPathToTkMenuPath
+#
+# Takes an entry path like .mbar.file.new and changes it to
+# .mbar.file.menu and performs a lookup in the pathMap to
+# get the corresponding menu widget name for tk
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_entryPathToTkMenuPath {entryPath} {
+
+ # get the menu path from the entry path name
+ # by stripping off the entry component of the path
+ regsub {[.][^.]*$} $entryPath "" menuPath
+
+ # the tkMenuPath is looked up with the .menu added to lookup
+ if { [catch {set tkMenuPath $_pathMap($menuPath.menu)}] } {
+ return ""
+ } else {
+ return $_pathMap($menuPath.menu)
+ }
+}
+
+
+# -------------------------------------------------------------
+#
+# These two methods address the issue of menu entry indices being
+# zero-based when the menu is not a tearoff menu and 1-based when
+# it is a tearoff menu. Our strategy is to hide this difference.
+#
+# _getTkIndex returns the index as tk likes it: 0 based for non-tearoff
+# and 1 based for tearoff menus.
+#
+# _getPdIndex (get pulldown index) always returns it as 0 based.
+#
+# -------------------------------------------------------------
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _getTkIndex
+#
+# give us a zero or 1-based answer depending on the tearoff
+# status of the menu. If the menu denoted by tkMenuPath is a
+# tearoff menu it returns a 1-based result, otherwise a
+# zero-based result.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_getTkIndex { tkMenuPath tkIndex} {
+
+ # if there is a tear off make it 1-based index
+ if { [$tkMenuPath cget -tearoff] } {
+ incr tkIndex
+ }
+
+ return $tkIndex
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _getPdIndex
+#
+# Take a tk index and give me a zero based numerical index
+#
+# Ask the menu widget for the index of the entry denoted by
+# 'tkIndex'. Then if the menu is a tearoff adjust the value
+# to be zero based.
+#
+# This method returns the index as if tearoffs did not exist.
+# Always returns a zero-based index.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_getPdIndex { tkMenuPath tkIndex } {
+
+ # get the index from the tk menu
+ # this 0 based for non-tearoff and 1-based for tearoffs
+ set pdIndex [$tkMenuPath index $tkIndex]
+
+ # if there is a tear off make it 0-based index
+ if { [$tkMenuPath cget -tearoff] } {
+ incr pdIndex -1
+ }
+
+ return $pdIndex
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _getMenuList
+#
+# Returns the list of menus in the order they are on the interface
+# returned list is a list of our menu paths
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_getMenuList { } {
+ # get the menus that are packed
+ set tkPathList [pack slaves $itk_component(menubar)]
+
+ regsub -- {[.]} $itk_component(hull) "" mbName
+ regsub -all -- "\[.\]$mbName\[.\]menubar\[.\]" $tkPathList "." menuPathList
+
+ return $menuPathList
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _getEntryList
+#
+#
+# This method looks at a menupath and gets all the entries and
+# returns a list of all the entry path names in numerical order
+# based on their index values.
+#
+# MENU is the path to a menu, like .mbar.file.menu or .mbar.file
+# we will calculate a menuPath from this: .mbar.file
+# then we will build a list of entries in this menu excluding the
+# path .mbar.file.menu
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_getEntryList { menu } {
+
+ # if it ends with menu, clip it off
+ regsub {[.]menu$} $menu "" menuPath
+
+ # first get the complete list of all menu paths
+ set pathList [array names _pathMap]
+
+ set numEntries 0
+ # iterate over the pathList and put on menuPathList those
+ # that match the menuPattern
+ foreach path $pathList {
+ # if this path is on the menuPath's branch
+ if { [regexp [subst -nocommands {$menuPath[.][^.]*$}] $path] } {
+ # if not a menu itself
+ if { ! [regexp {[.]menu$} $path] } {
+ set orderedList($_pathMap($path)) $path
+ incr numEntries
+ }
+ }
+ }
+ set entryList {}
+
+ for {set i 0} {$i < $numEntries} {incr i} {
+ lappend entryList $orderedList($i)
+ }
+
+ return $entryList
+
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _parsePath
+#
+# given path, PATH, _parsePath splits the path name into its
+# component segments. It then puts the name back together one
+# segment at a time and calls _getSymbolicPath to replace the
+# keywords 'last' and 'end' as well as numeric digits.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_parsePath { path } {
+ set segments [split [string trimleft $path .] .]
+
+ set concatPath ""
+ foreach seg $segments {
+
+ set concatPath [_getSymbolicPath $concatPath $seg]
+
+ if { [catch {set _pathMap($concatPath)} ] } {
+ error "bad path: \"$path\" does not exist. \"$seg\" not valid"
+ }
+ }
+ return $concatPath
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _getSymbolicPath
+#
+# Given a PATH, _getSymbolicPath looks for the last segment of
+# PATH to contain: a number, the keywords last or end. If one
+# of these it figures out how to get us the actual pathname
+# to the searched widget
+#
+# Implementor's notes:
+# Surely there is a shorter way to do this. The only diff
+# for non-numeric is getting the llength of the correct list
+# It is hard to know this upfront so it seems harder to generalize.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_getSymbolicPath { parent segment } {
+
+ # if the segment is a number, then look it up positionally
+ # MATCH numeric index
+ if { [regexp {^[0-9]+$} $segment] } {
+
+ # if we have no parent, then we area menubutton
+ if { $parent == {} } {
+ set returnPath [lindex [_getMenuList] $segment]
+ } else {
+ set returnPath [lindex [_getEntryList $parent.menu] $segment]
+ }
+
+ # MATCH 'end' or 'last' keywords.
+ } elseif { $segment == "end" || $segment == "last" } {
+
+ # if we have no parent, then we are a menubutton
+ if { $parent == {} } {
+ set returnPath [lindex [_getMenuList] end]
+ } else {
+ set returnPath [lindex [_getEntryList $parent.menu] end]
+ }
+ } else {
+ set returnPath $parent.$segment
+ }
+
+ return $returnPath
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _helpHandler
+#
+# Bound to the <Motion> event on a menu pane. This puts the
+# help string associated with the menu entry into the
+# status widget help area. If no help exists for the current
+# entry, the status widget is cleared.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_helpHandler { menuPath } {
+
+ if { $itk_option(-helpvariable) == {} } {
+ return
+ }
+
+ set tkMenuWidget $_pathMap($menuPath)
+
+ set entryIndex [$tkMenuWidget index active]
+
+ # already on this item?
+ if { $entryIndex == $_entryIndex } {
+ return
+ }
+
+ set _entryIndex $entryIndex
+
+ if {"none" != $entryIndex} {
+ set entries [_getEntryList $menuPath]
+
+ set menuEntryHit \
+ [lindex $entries [_getPdIndex $tkMenuWidget $entryIndex]]
+
+ # blank out the old one
+ set $itk_option(-helpvariable) {}
+
+ # if there is a help string for this entry
+ if { [::info exists _helpString($menuEntryHit)] } {
+ set $itk_option(-helpvariable) $_helpString($menuEntryHit)
+ }
+ } else {
+ set $itk_option(-helpvariable) {}
+ set _entryIndex -1
+ }
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _getCallerLevel
+#
+# Starts at stack frame #0 and works down till we either hit
+# a ::Menubar stack frame or an ::itk::Archetype stack frame
+# (the latter happens when a configure is called via the 'component'
+# method
+#
+# Returns the level of the actual caller of the menubar command
+# in the form of #num where num is the level number caller stack frame.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Menubar::_getCallerLevel { } {
+
+ set levelName {}
+ set levelsAreValid true
+ set level 0
+ set callerLevel #$level
+
+ while { $levelsAreValid } {
+ # Hit the end of the stack frame
+ if [catch {uplevel #$level {namespace current}}] {
+ set levelsAreValid false
+ set callerLevel #[expr {$level - 1}]
+ # still going
+ } else {
+ set newLevelName [uplevel #$level {namespace current}]
+ # See if we have run into the first ::Menubar level
+ if { $newLevelName == "::itk::Archetype" || \
+ $newLevelName == "::iwidgets::Menubar" } {
+ # If so, we are done-- set the callerLevel
+ set levelsAreValid false
+ set callerLevel #[expr {$level - 1}]
+ } else {
+ set levelName $newLevelName
+ }
+ }
+ incr level
+ }
+ return $callerLevel
+}
+
+
+#
+# The default tkMenuFind proc in menu.tcl only looks for menubuttons
+# in frames. Since our menubuttons are within the Menubar class, the
+# default proc won't find them during menu traversal. This proc
+# redefines the default proc to remedy the problem.
+#-----------------------------------------------------------
+# BUG FIX: csmith (Chad Smith: csmith@adc.com), 3/30/99
+#-----------------------------------------------------------
+# The line, "set qchild ..." below had a typo. It should be
+# "info command $child" instead of "winfo command $child".
+#-----------------------------------------------------------
+proc tkMenuFind {w char} {
+ global tkPriv
+ set char [string tolower $char]
+
+ # Added by csmith, 5/10/01, to fix a bug reported on the itcl mailing list.
+ if {$w == "."} {
+ foreach child [winfo child $w] {
+ set match [tkMenuFind $child $char]
+ if {$match != ""} {
+ return $match
+ }
+ }
+ return {}
+ }
+
+ foreach child [winfo child $w] {
+ switch [winfo class $child] {
+ Menubutton {
+ set qchild [info command $child]
+ set char2 [string index [$qchild cget -text] \
+ [$qchild cget -underline]]
+ if {([string compare $char [string tolower $char2]] == 0)
+ || ($char == "")} {
+ if {[$qchild cget -state] != "disabled"} {
+ return $child
+ }
+ }
+ }
+ Frame -
+ Menubar {
+ set match [tkMenuFind $child $char]
+ if {$match != ""} {
+ return $match
+ }
+ }
+ }
+ }
+ return {}
+}
diff --git a/iwidgets/generic/messagebox.itk b/iwidgets/generic/messagebox.itk
new file mode 100644
index 00000000000..40cad1caad9
--- /dev/null
+++ b/iwidgets/generic/messagebox.itk
@@ -0,0 +1,399 @@
+#
+# Messagebox
+# ----------------------------------------------------------------------
+# Implements an information messages area widget with scrollbars.
+# Message types can be user defined and configured. Their options
+# include foreground, background, font, bell, and their display
+# mode of on or off. This allows message types to defined as needed,
+# removed when no longer so, and modified when necessary. An export
+# method is provided for file I/O.
+#
+# The number of lines that can be displayed may be limited with
+# the default being 1000. When this limit is reached, the oldest line
+# is removed. There is also support for saving the contents to a
+# file, using a file selection dialog.
+# ----------------------------------------------------------------------
+#
+# History:
+# 01/16/97 - Alfredo Jahn Renamed from InfoMsgBox to MessageBox
+# Initial release...
+# 01/20/97 - Alfredo Jahn Add a popup window so that 3rd mouse
+# button can be used to configure/access the message area.
+# New methods added: _post and _toggleDebug.
+# 01/30/97 - Alfredo Jahn Add -filename option
+# 05/11/97 - Mark Ulferts Added the ability to define and configure
+# new types. Changed print method to be issue.
+# 09/05/97 - John Tucker Added export method.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Alfredo Jahn V EMAIL: ajahn@spd.dsccc.com
+# Mark L. Ulferts mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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 Messagebox {
+ keep -activebackground -activeforeground -background -borderwidth \
+ -cursor -highlightcolor -highlightthickness \
+ -jump -labelfont -textbackground -troughcolor
+}
+
+# ------------------------------------------------------------------
+# MSGTYPE
+# ------------------------------------------------------------------
+
+itcl::class iwidgets::MsgType {
+ constructor {args} {eval configure $args}
+
+ public variable background \#d9d9d9
+ public variable bell 0
+ public variable font -*-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*
+ public variable foreground Black
+ public variable show 1
+}
+
+# ------------------------------------------------------------------
+# MESSAGEBOX
+# ------------------------------------------------------------------
+itcl::class iwidgets::Messagebox {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -filename fileName FileName ""
+ itk_option define -maxlines maxLines MaxLines 1000
+ itk_option define -savedir saveDir SaveDir "[pwd]"
+
+ public {
+ method clear {}
+ method export {filename}
+ method find {}
+ method issue {string {type DEFAULT} args}
+ method save {}
+ method type {op tag args}
+ }
+
+ protected {
+ variable _unique 0
+ variable _types {}
+ variable _interior {}
+
+ method _post {x y}
+ }
+}
+
+#
+# Provide a lowercased access method for the Messagebox class.
+#
+proc ::iwidgets::messagebox {pathName args} {
+ uplevel ::iwidgets::Messagebox $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Messagebox.labelPos n widgetDefault
+option add *Messagebox.cursor top_left_arrow widgetDefault
+option add *Messagebox.height 0 widgetDefault
+option add *Messagebox.width 0 widgetDefault
+option add *Messagebox.visibleItems 80x24 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagebox::constructor {args} {
+ set _interior $itk_interior
+
+ #
+ # Create the text area.
+ #
+ itk_component add text {
+ iwidgets::Scrolledtext $itk_interior.text -width 1 -height 1 \
+ -state disabled -wrap none
+ } {
+ keep -borderwidth -cursor -exportselection -highlightcolor \
+ -highlightthickness -padx -pady -relief -setgrid -spacing1 \
+ -spacing2 -spacing3
+
+ keep -activerelief -elementborderwidth -jump -troughcolor
+
+ keep -hscrollmode -height -sbwidth -scrollmargin -textbackground \
+ -visibleitems -vscrollmode -width
+
+ keep -labelbitmap -labelfont -labelimage -labelmargin \
+ -labelpos -labeltext -labelvariable
+ }
+ grid $itk_component(text) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 0 -weight 1
+
+ #
+ # Setup right mouse button binding to post a user configurable
+ # popup menu and diable the binding for left mouse clicks.
+ #
+ bind [$itk_component(text) component text] <ButtonPress-1> "break"
+ bind [$itk_component(text) component text] \
+ <ButtonPress-3> [itcl::code $this _post %x %y]
+
+ #
+ # Create the small popup menu that can be configurable by users.
+ #
+ itk_component add itemMenu {
+ menu $itk_component(hull).itemmenu -tearoff 0
+ } {
+ keep -background -font -foreground \
+ -activebackground -activeforeground
+ ignore -tearoff
+ }
+
+ #
+ # Add clear and svae options to the popup menu.
+ #
+ $itk_component(itemMenu) add command -label "Find" \
+ -command [itcl::code $this find]
+ $itk_component(itemMenu) add command -label "Save" \
+ -command [itcl::code $this save]
+ $itk_component(itemMenu) add command -label "Clear" \
+ -command [itcl::code $this clear]
+
+ #
+ # Create a standard type to be used if no others are specified.
+ #
+ type add DEFAULT
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTURCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagebox::destructor {} {
+ foreach type $_types {
+ type remove $type
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD clear
+#
+# Clear the text area.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagebox::clear {} {
+ $itk_component(text) configure -state normal
+
+ $itk_component(text) delete 1.0 end
+
+ $itk_component(text) configure -state disabled
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: type <op> <tag> <args>
+#
+# The type method supports several subcommands. Types can be added
+# removed and configured. All the subcommands use the MsgType class
+# to implement the functionaility.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagebox::type {op tag args} {
+ switch $op {
+ add {
+ eval iwidgets::MsgType $this$tag $args
+
+ lappend _types $tag
+
+ $itk_component(text) tag configure $tag \
+ -font [$this$tag cget -font] \
+ -background [$this$tag cget -background] \
+ -foreground [$this$tag cget -foreground]
+
+ return $tag
+ }
+
+ remove {
+ if {[set index [lsearch $_types $tag]] != -1} {
+ itcl::delete object $this$tag
+ set _types [lreplace $_types $index $index]
+
+ return
+ } else {
+ error "bad message type: \"$tag\", does not exist"
+ }
+ }
+
+ configure {
+ if {[set index [lsearch $_types $tag]] != -1} {
+ set retVal [eval $this$tag configure $args]
+
+ $itk_component(text) tag configure $tag \
+ -font [$this$tag cget -font] \
+ -background [$this$tag cget -background] \
+ -foreground [$this$tag cget -foreground]
+
+ return $retVal
+
+ } else {
+ error "bad message type: \"$tag\", does not exist"
+ }
+ }
+
+ cget {
+ if {[set index [lsearch $_types $tag]] != -1} {
+ return [eval $this$tag cget $args]
+ } else {
+ error "bad message type: \"$tag\", does not exist"
+ }
+ }
+
+ default {
+ error "bad type operation: \"$op\", should be add,\
+ remove, configure or cget"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: issue string ?type? args
+#
+# Print the string out to the Messagebox. Check the options of the
+# message type to see if it should be displayed or if the bell
+# should be wrong.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagebox::issue {string {type DEFAULT} args} {
+ if {[lsearch $_types $type] == -1} {
+ error "bad message type: \"$type\", use the type\
+ command to create a new types"
+ }
+
+ #
+ # If the type is currently configured to be displayed, then insert
+ # it in the text widget, add the tag to the line and move the
+ # vertical scroll bar to the bottom.
+ #
+ set tag $this$type
+
+ if {[$tag cget -show]} {
+ $itk_component(text) configure -state normal
+
+ #
+ # Find end of last message.
+ #
+ set prevend [$itk_component(text) index "end - 1 chars"]
+
+ $itk_component(text) insert end "$string\n" $args
+
+ $itk_component(text) tag add $type $prevend "end - 1 chars"
+ $itk_component(text) yview end
+
+ #
+ # Sound a beep if the message type is configured such.
+ #
+ if {[$tag cget -bell]} {
+ bell
+ }
+
+ #
+ # If we reached our max lines limit, then remove enough lines to
+ # get it back under.
+ #
+ set lineCount [lindex [split [$itk_component(text) index end] "."] 0]
+
+ if { $lineCount > $itk_option(-maxlines) } {
+ set numLines [expr {$lineCount - $itk_option(-maxlines) -1}]
+
+ $itk_component(text) delete 1.0 $numLines.0
+ }
+
+ $itk_component(text) configure -state disabled
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: save
+#
+# Save contents of messages area to a file using a fileselectionbox.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagebox::save {} {
+ set saveFile ""
+ set filter ""
+
+ set saveFile [tk_getSaveFile -title "Save Messages" \
+ -initialdir $itk_option(-savedir) \
+ -parent $itk_interior \
+ -initialfile $itk_option(-filename)]
+
+ if { $saveFile != "" } {
+ $itk_component(text) export $saveFile
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: find
+#
+# Search the contents of messages area for a specific string.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagebox::find {} {
+ if {! [info exists itk_component(findd)]} {
+ itk_component add findd {
+ iwidgets::Finddialog $itk_interior.findd \
+ -textwidget $itk_component(text)
+ }
+ }
+
+ $itk_component(findd) center $itk_component(text)
+ $itk_component(findd) activate
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _post
+#
+# Used internally to post the popup menu at the coordinate (x,y)
+# relative to the widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagebox::_post {x y} {
+ set rx [expr {[winfo rootx $itk_component(text)]+$x}]
+ set ry [expr {[winfo rooty $itk_component(text)]+$y}]
+
+ tk_popup $itk_component(itemMenu) $rx $ry
+}
+
+
+# ------------------------------------------------------------------
+# METHOD export filename
+#
+# write text to a file (export filename)
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagebox::export {filename} {
+
+ $itk_component(text) export $filename
+
+}
+
diff --git a/iwidgets/generic/messagedialog.itk b/iwidgets/generic/messagedialog.itk
new file mode 100644
index 00000000000..2b9c58fb733
--- /dev/null
+++ b/iwidgets/generic/messagedialog.itk
@@ -0,0 +1,144 @@
+#
+# Messagedialog
+# ----------------------------------------------------------------------
+# Implements a message dialog composite widget. The Messagedialog is
+# derived from the Dialog class and is composed of an image and text
+# component. The image will accept both images as well as bitmaps.
+# The text can extend mutliple lines by embedding newlines.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Messagedialog {
+ keep -background -cursor -font -foreground -modality
+ keep -wraplength -justify
+}
+
+# ------------------------------------------------------------------
+# MESSAGEDIALOG
+# ------------------------------------------------------------------
+itcl::class iwidgets::Messagedialog {
+ inherit iwidgets::Dialog
+
+ constructor {args} {}
+
+ itk_option define -imagepos imagePos Position w
+}
+
+#
+# Provide a lowercased access method for the Messagedialog class.
+#
+proc ::iwidgets::messagedialog {pathName args} {
+ uplevel ::iwidgets::Messagedialog $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Messagedialog.title "Message Dialog" widgetDefault
+option add *Messagedialog.master "." widgetDefault
+option add *Messagedialog.textPadX 20 widgetDefault
+option add *Messagedialog.textPadY 20 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Messagedialog::constructor {args} {
+ #
+ # Create the image component which may be either a bitmap or image.
+ #
+ itk_component add image {
+ label $itk_interior.image
+ } {
+ keep -background -bitmap -cursor -foreground -image
+ }
+
+ #
+ # Create the text message component. The message may extend over
+ # several lines by embedding '\n' characters.
+ #
+ itk_component add message {
+ label $itk_interior.message
+ } {
+ keep -background -cursor -font -foreground -text
+ keep -wraplength -justify
+
+ rename -padx -textpadx textPadX Pad
+ rename -pady -textpady textPadY Pad
+ }
+
+ #
+ # Hide the apply and help buttons.
+ #
+ hide Apply
+ hide Help
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -imagepos
+#
+# Specifies the image position relative to the message: n, s,
+# e, or w. The default is w.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Messagedialog::imagepos {
+ switch $itk_option(-imagepos) {
+ n {
+ grid $itk_component(image) -row 0 -column 0
+ grid $itk_component(message) -row 1 -column 0
+ }
+ s {
+ grid $itk_component(message) -row 0 -column 0
+ grid $itk_component(image) -row 1 -column 0
+ }
+ e {
+ grid $itk_component(message) -row 0 -column 0
+ grid $itk_component(image) -row 0 -column 1
+ }
+ w {
+ grid $itk_component(image) -row 0 -column 0
+ grid $itk_component(message) -row 0 -column 1
+ }
+
+ default {
+ error "bad imagepos option \"$itk_option(-imagepos)\":\
+ should be n, e, s, or w"
+ }
+ }
+}
diff --git a/iwidgets/generic/notebook.itk b/iwidgets/generic/notebook.itk
new file mode 100644
index 00000000000..18c5cd95efe
--- /dev/null
+++ b/iwidgets/generic/notebook.itk
@@ -0,0 +1,946 @@
+#
+# Notebook Widget
+# ----------------------------------------------------------------------
+# The Notebook command creates a new window (given by the pathName
+# argument) and makes it into a Notebook widget. Additional options,
+# described above may be specified on the command line or in the
+# option database to configure aspects of the Notebook such as its
+# colors, font, and text. The Notebook command returns its pathName
+# argument. At the time this command is invoked, there must not exist
+# a window named pathName, but path Name's parent must exist.
+#
+# A Notebook is a widget that contains a set of pages. It displays one
+# page from the set as the selected page. When a page is selected, the
+# page's contents are displayed in the page area. When first created a
+# Notebook has no pages. Pages may be added or deleted using widget commands
+# described below.
+#
+# A special option may be provided to the Notebook. The -auto option
+# specifies whether the Nptebook will automatically handle the unpacking
+# and packing of pages when pages are selected. A value of true signifies
+# that the notebook will automatically manage it. This is the default
+# value. A value of false signifies the notebook will not perform automatic
+# switching of pages.
+#
+# WISH LIST:
+# This section lists possible future enhancements.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Bill W. Scott EMAIL: bscott@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Notebook.background #d9d9d9 widgetDefault
+option add *Notebook.auto true widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Notebook {
+ keep -background -cursor
+}
+
+# ------------------------------------------------------------------
+# NOTEBOOK
+# ------------------------------------------------------------------
+itcl::class iwidgets::Notebook {
+ inherit itk::Widget
+
+ constructor {args} {}
+
+ itk_option define -background background Background #d9d9d9
+ itk_option define -auto auto Auto true
+ itk_option define -scrollcommand scrollCommand ScrollCommand {}
+
+ public method add { args }
+ public method childsite { args }
+ public method delete { args }
+ public method index { args }
+ public method insert { args }
+ public method prev { }
+ public method next { }
+ public method pageconfigure { args }
+ public method pagecget { index option }
+ public method select { index }
+ public method view { args }
+
+ private method _childSites { }
+ private method _scrollCommand { }
+ private method _index { pathList index select}
+ private method _createPage { args }
+ private method _deletePages { fromPage toPage }
+ private method _configurePages { args }
+ private method _tabCommand { }
+
+ private variable _currPage -1 ;# numerical index of current page selected
+ private variable _pages {} ;# list of Page components
+ private variable _uniqueID 0 ;# one-up number for unique page numbering
+
+}
+
+#
+# Provide a lowercase access method for the Notebook class
+#
+proc ::iwidgets::notebook {pathName args} {
+ uplevel ::iwidgets::Notebook $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::constructor {args} {
+ #
+ # Create the outermost frame to maintain geometry.
+ #
+ itk_component add cs {
+ frame $itk_interior.cs
+ } {
+ keep -cursor -background -width -height
+ }
+ pack $itk_component(cs) -fill both -expand yes
+ pack propagate $itk_component(cs) no
+
+ eval itk_initialize $args
+
+ # force bg of all pages to reflect Notebook's background.
+ _configurePages -background $itk_option(-background)
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+# ------------------------------------------------------------------
+# OPTION -background
+#
+# Sets the bg color of all the pages in the Notebook.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Notebook::background {
+ if {$itk_option(-background) != {}} {
+ _configurePages -background $itk_option(-background)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION -auto
+#
+# Determines whether pages are automatically unpacked and
+# packed when pages get selected.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Notebook::auto {
+ if {$itk_option(-auto) != {}} {
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION -scrollcommand
+#
+# Command string to be invoked when the notebook
+# has any changes to its current page, or number of pages.
+#
+# typically for scrollbars.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Notebook::scrollcommand {
+ if {$itk_option(-scrollcommand) != {}} {
+ _scrollCommand
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: add add ?<option> <value>...?
+#
+# Creates a page and appends it to the list of pages.
+# processes pageconfigure for the page added.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::add { args } {
+ # The args list should be an even # of params, if not then
+ # prob missing value for last item in args list. Signal error.
+ set len [llength $args]
+ if {$len % 2} {
+ error "value for \"[lindex $args [expr {$len - 1}]]\" missing"
+ }
+
+ # add a Page component
+ set pathName [eval _createPage $args]
+ lappend _pages $pathName
+
+ # update scroller
+ _scrollCommand
+
+ # return childsite for the Page component
+ return [eval $pathName childsite]
+}
+
+# ------------------------------------------------------------------
+# METHOD: childsite ?<index>?
+#
+# If index is supplied, returns the child site widget corresponding
+# to the page index. If called with no arguments, returns a list
+# of all child sites
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::childsite { args } {
+ set len [llength $args]
+
+ switch $len {
+ 0 {
+ # ... called with no arguments, return a list
+ if { [llength $args] == 0 } {
+ return [_childSites]
+ }
+ }
+ 1 {
+ set index [lindex $args 0]
+ # ... otherwise, return child site for the index given
+ # empty notebook
+ if { $_pages == {} } {
+ error "can't get childsite,\
+ no pages in the notebook \"$itk_component(hull)\""
+ }
+
+ set index [_index $_pages $index $_currPage]
+
+ # index out of range
+ if { $index < 0 || $index >= [llength $_pages] } {
+ error "bad Notebook page index in childsite method:\
+ should be between 0 and [expr {[llength $_pages] - 1}]"
+ }
+
+ set pathName [lindex $_pages $index]
+
+ set cs [eval $pathName childsite]
+ return $cs
+ }
+ default {
+ # ... too many parameters passed
+ error "wrong # args: should be\
+ \"$itk_component(hull) childsite ?index?\""
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete <index1> ?<index2>?
+#
+# Deletes a page or range of pages from the notebook
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::delete { args } {
+ # empty notebook
+ if { $_pages == {} } {
+ error "can't delete page, no pages in the notebook\
+ \"$itk_component(hull)\""
+ }
+
+ set len [llength $args]
+ switch -- $len {
+ 1 {
+ set fromPage [_index $_pages [lindex $args 0] $_currPage]
+
+ if { $fromPage < 0 || $fromPage >= [llength $_pages] } {
+ error "bad Notebook page index in delete method:\
+ should be between 0 and [expr {[llength $_pages] - 1}]"
+ }
+
+ set toPage $fromPage
+ _deletePages $fromPage $toPage
+ }
+
+ 2 {
+ set fromPage [_index $_pages [lindex $args 0] $_currPage]
+
+ if { $fromPage < 0 || $fromPage >= [llength $_pages] } {
+ error "bad Notebook page index1 in delete method:\
+ should be between 0 and [expr {[llength $_pages] - 1}]"
+ }
+
+ set toPage [_index $_pages [lindex $args 1] $_currPage]
+
+ if { $toPage < 0 || $toPage >= [llength $_pages] } {
+ error "bad Notebook page index2 in delete method:\
+ should be between 0 and [expr {[llength $_pages] - 1}]"
+ error "bad Notebook page index2"
+ }
+
+ if { $fromPage > $toPage } {
+ error "bad Notebook page index1 in delete method:\
+ index1 is greater than index2"
+ }
+
+ _deletePages $fromPage $toPage
+
+ }
+
+ default {
+ # ... too few/many parameters passed
+ error "wrong # args: should be\
+ \"$itk_component(hull) delete index1 ?index2?\""
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: index <index>
+#
+# Given an index identifier returns the numeric index of the page
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::index { args } {
+ if { [llength $args] != 1 } {
+ error "wrong # args: should be\
+ \"$itk_component(hull) index index\""
+ }
+
+ set index $args
+
+ set number [_index $_pages $index $_currPage]
+
+ return $number
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert <index> ?<option> <value>...?
+#
+# Inserts a page before a index. The before page may
+# be specified as a label or a page position.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::insert { args } {
+ # ... Error: no args passed
+ set len [llength $args]
+ if { $len == 0 } {
+ error "wrong # args: should be\
+ \"$itk_component(hull) insert index ?option value?\""
+ }
+
+ # ... set up index and args
+ set index [lindex $args 0]
+ set args [lrange $args 1 $len]
+
+ # ... Error: unmatched option value pair (len is odd)
+ # The args list should be an even # of params, if not then
+ # prob missing value for last item in args list. Signal error.
+ set len [llength $args]
+ if { $len % 2 } {
+ error "value for \"[lindex $args [expr {$len - 1}]]\" missing"
+ }
+
+ # ... Error: catch notebook empty
+ if { $_pages == {} } {
+ error "can't insert page, no pages in the notebook\
+ \"$itk_component(hull)\""
+ }
+
+ # ok, get the page
+ set page [_index $_pages $index $_currPage]
+
+ # ... Error: catch bad value for before page.
+ if { $page < 0 || $page >= [llength $_pages] } {
+ error "bad Notebook page index in insert method:\
+ should be between 0 and [expr {[llength $_pages] - 1}]"
+ }
+
+ # ... Start the business of inserting
+ # create the new page and get its path name...
+ set pathName [eval _createPage $args]
+
+ # grab the name of the page currently selected. (to keep in sync)
+ set currPathName [lindex $_pages $_currPage]
+
+ # insert pathName before $page
+ set _pages [linsert $_pages $page $pathName]
+
+ # keep the _currPage in sync with the insert.
+ set _currPage [lsearch -exact $_pages $currPathName]
+
+ # give scrollcommand chance to update
+ _scrollCommand
+
+ # give them child site back...
+ return [eval $pathName childsite]
+}
+
+# ------------------------------------------------------------------
+# METHOD: prev
+#
+# Selects the previous page. Wraps at first back to last page.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::prev { } {
+ # catch empty notebook
+ if { $_pages == {} } {
+ error "can't move to previous page,\
+ no pages in the notebook \"$itk_component(hull)\""
+ }
+
+ # bump to the previous page and wrap if necessary
+ set prev [expr {$_currPage - 1}]
+ if { $prev < 0 } {
+ set prev [expr {[llength $_pages] - 1}]
+ }
+
+ select $prev
+
+ return $prev
+}
+
+# ------------------------------------------------------------------
+# METHOD: next
+#
+# Selects the next page. Wraps at last back to first page.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::next { } {
+ # catch empty notebook
+ if { $_pages == {} } {
+ error "can't move to next page,\
+ no pages in the notebook \"$itk_component(hull)\""
+ }
+
+ # bump to the next page and wrap if necessary
+ set next [expr {$_currPage + 1}]
+ if { $next >= [llength $_pages] } {
+ set next 0
+ }
+
+ select $next
+
+ return $next
+}
+
+# ------------------------------------------------------------------
+# METHOD: pageconfigure <index> ?<option> <value>...?
+#
+# Performs configure on a given page denoted by index. Index may
+# be a page number or a pattern matching the label associated with
+# a page.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::pageconfigure { args } {
+ # ... Error: no args passed
+ set len [llength $args]
+ if { $len == 0 } {
+ error "wrong # args: should be\
+ \"$itk_component(hull) pageconfigure index ?option value?\""
+ }
+
+ # ... set up index and args
+ set index [lindex $args 0]
+ set args [lrange $args 1 $len]
+
+ set page [_index $_pages $index $_currPage]
+
+ # ... Error: page out of range
+ if { $page < 0 || $page >= [llength $_pages] } {
+ error "bad Notebook page index in pageconfigure method:\
+ should be between 0 and [expr {[llength $_pages] - 1}]"
+ }
+
+ # Configure the page component
+ set pathName [lindex $_pages $page]
+ return [eval $pathName configure $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: pagecget <index> <option>
+#
+# Performs cget on a given page denoted by index. Index may
+# be a page number or a pattern matching the label associated with
+# a page.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::pagecget { index option } {
+ set page [_index $_pages $index $_currPage]
+
+ # ... Error: page out of range
+ if { $page < 0 || $page >= [llength $_pages] } {
+ error "bad Notebook page index in pagecget method:\
+ should be between 0 and [expr {[llength $_pages] - 1}]"
+ }
+
+ # Get the page info.
+ set pathName [lindex $_pages $page]
+ return [$pathName cget $option]
+}
+
+# ------------------------------------------------------------------
+# METHOD: select <index>
+#
+# Select a page by index. Hide the last _currPage if it existed.
+# Then show the new one if it exists. Returns the currently
+# selected page or -1 if tried to do a select select when there is
+# no selection.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::select { index } {
+ global page$itk_component(hull)
+
+ # ... Error: empty notebook
+ if { $_pages == {} } {
+ error "can't select page $index,\
+ no pages in the notebook \"$itk_component(hull)\""
+ }
+
+ # if there is not current selection just ignore trying this selection
+ if { $index == "select" && $_currPage == -1 } {
+ return -1
+ }
+
+ set reqPage [_index $_pages $index $_currPage]
+
+ if { $reqPage < 0 || $reqPage >= [llength $_pages] } {
+ error "bad Notebook page index in select method:\
+ should be between 0 and [expr {[llength $_pages] - 1}]"
+ }
+
+ # if we already have this page selected, then ignore selection.
+ if { $reqPage == $_currPage } {
+ return $_currPage
+ }
+
+ # if we are handling packing and unpacking the unpack if we can
+ if { $itk_option(-auto) } {
+ # if there is a current page packed, then unpack it
+ if { $_currPage != -1 } {
+ set currPathName [lindex $_pages $_currPage]
+ pack forget $currPathName
+ }
+ }
+
+ # set this now so that the -command cmd can do an 'index select'
+ # to operate on this page.
+ set _currPage $reqPage
+
+ # invoke the command for this page
+ set cmd [lindex [pageconfigure $index -command] 4]
+ eval $cmd
+
+ # give scrollcommand chance to update
+ _scrollCommand
+
+ # if we are handling packing and unpacking the pack if we can
+ if { $itk_option(-auto) } {
+ set reqPathName [lindex $_pages $reqPage]
+ pack $reqPathName -anchor nw -fill both -expand yes
+ }
+
+ return $_currPage
+}
+
+
+# ------------------------------------------------------------------
+# METHOD: view
+#
+# Return the current page
+#
+# view <index>
+#
+# Selects the page denoted by index to be current page
+#
+# view 'moveto' <fraction>
+#
+# Selects the page by using fraction amount
+#
+# view 'scroll' <num> <what>
+#
+# Selects the page by using num as indicator of next or previous
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::view { args } {
+ set len [llength $args]
+ switch -- $len {
+ 0 {
+ # Return current page
+ return $_currPage
+ }
+ 1 {
+ # Select by index
+ select [lindex $args 0]
+ }
+ 2 {
+ # Select using moveto
+ set arg [lindex $args 0]
+ if { $arg == "moveto" } {
+ set fraction [lindex $args 1]
+ if { [catch { set page \
+ [expr {round($fraction/(1.0/[llength $_pages]))}]}]} {
+ error "expected floating-point number \
+ but got \"$fraction\""
+ }
+ if { $page == [llength $_pages] } {
+ incr page -1
+ }
+
+ if { $page >= 0 && $page < [llength $_pages] } {
+ select $page
+ }
+ } else {
+ error "expected \"moveto\" but got $arg"
+ }
+ }
+ 3 {
+ # Select using scroll keyword
+ set arg [lindex $args 0]
+ if { $arg == "scroll" } {
+ set amount [lindex $args 1]
+ # check for integer value
+ if { ! [regexp {^[-]*[0-9]*$} $amount] } {
+ error "expected integer but got \"$amount\""
+ }
+ set page [expr {$_currPage + $amount}]
+ if { $page >= 0 && $page < [llength $_pages] } {
+ select $page
+ }
+
+ } else {
+ error "expected \"scroll\" but got $arg"
+ }
+ }
+ default {
+ set arg [lindex $args 0]
+ if { $arg == "moveto" } {
+ error "wrong # args: should be\
+ \"$itk_component(hull) view moveto fraction\""
+ } elseif { $arg == "scroll" } {
+ error "wrong # args: should be\
+ \"$itk_component(hull) view scroll units|pages\""
+ } else {
+ error "wrong # args: should be\
+ \"$itk_component(hull) view index\""
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _childSites
+#
+# Returns a list of child sites for all pages in the notebook.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::_childSites { } {
+ # empty notebook
+ if { $_pages == {} } {
+ error "can't get childsite list,\
+ no pages in the notebook \"$itk_component(hull)\""
+ }
+
+ set csList {}
+
+ foreach pathName $_pages {
+ lappend csList [eval $pathName childsite]
+ }
+
+ return $csList
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _scrollCommand
+#
+# If there is a -scrollcommand set up, then call the tcl command
+# and suffix onto it the standard 4 numbers scrollbars get.
+#
+# Invoke the scrollcommand, this is like the y/xscrollcommand
+# it is designed to talk to scrollbars and the the
+# tabset also knows how to obey scrollbar protocol.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::_scrollCommand { } {
+ if { $itk_option(-scrollcommand) != {} } {
+ if { $_currPage != -1 } {
+ set relTop [expr {($_currPage*1.0) / [llength $_pages]}]
+ set relBottom [expr {(($_currPage+1)*1.0) / [llength $_pages]}]
+ set scrollCommand "$itk_option(-scrollcommand) $relTop $relBottom"
+ } else {
+ set scrollCommand "$itk_option(-scrollcommand) 0 1"
+ }
+ uplevel #0 $scrollCommand
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _index
+#
+# pathList : list of path names to search thru if index is a label
+# index : either number, 'select', 'end', or pattern
+# select : current selection
+#
+# _index takes takes the value $index converts it to
+# a numeric identifier. If the value is not already
+# an integer it looks it up in the $pathList array.
+# If it fails it returns -1
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::_index { pathList index select} {
+ switch -- $index {
+ select {
+ set number $select
+ }
+ end {
+ set number [expr {[llength $pathList] -1}]
+ }
+ default {
+ # is it a number already?
+ if { [regexp {^[0-9]+$} $index] } {
+ set number $index
+ if { $number < 0 || $number >= [llength $pathList] } {
+ set number -1
+ }
+
+ # otherwise it is a label
+ } else {
+ # look thru the pathList of pathNames and
+ # get each label and compare with index.
+ # if we get a match then set number to postion in $pathList
+ # and break out.
+ # otherwise number is still -1
+ set i 0
+ set number -1
+ foreach pathName $pathList {
+ set label [lindex [$pathName configure -label] 4]
+ if { [string match $label $index] } {
+ set number $i
+ break
+ }
+ incr i
+ }
+ }
+ }
+ }
+
+ return $number
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _createPage
+#
+# Creates a page, using unique page naming, propagates background
+# and keeps unique id up to date.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::_createPage { args } {
+ #
+ # create an internal name for the page: .n.cs.page0, .n.cs.page1, etc.
+ #
+ set pathName $itk_component(cs).page$_uniqueID
+
+ eval iwidgets::Page $pathName -background $itk_option(-background) $args
+
+ incr _uniqueID
+ return $pathName
+
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _deletePages
+#
+# Deletes pages from $fromPage to $toPage.
+#
+# Operates in two passes, destroys all the widgets
+# Then removes the pathName from the page list
+#
+# Also keeps the current selection in bounds.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::_deletePages { fromPage toPage } {
+ for { set page $fromPage } { $page <= $toPage } { incr page } {
+ # kill the widget
+ set pathName [lindex $_pages $page]
+ destroy $pathName
+ }
+
+ # physically remove the page
+ set _pages [lreplace $_pages $fromPage $toPage]
+
+ # If we deleted a selected page set our selection to none
+ if { $_currPage >= $fromPage && $_currPage <= $toPage } {
+ set _currPage -1
+ }
+
+ # make sure _currPage stays in sync with new numbering...
+ if { $_pages == {} } {
+ # if deleted only remaining page,
+ # reset current page to undefined
+ set _currPage -1
+
+ # or if the current page was the last page, it needs come back
+ } elseif { $_currPage >= [llength $_pages] } {
+ incr _currPage -1
+ if { $_currPage < 0 } {
+ # but only to zero
+ set _currPage 0
+ }
+ }
+
+ # give scrollcommand chance to update
+ _scrollCommand
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _configurePages
+#
+# Does the pageconfigure method on each page in the notebook
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::_configurePages { args } {
+ # make sure we have pages
+ if { [catch {set _pages}] } {
+ return
+ }
+
+ # go thru all pages and pageconfigure them.
+ foreach pathName $_pages {
+ eval "$pathName configure $args"
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _tabCommand
+#
+# Calls the command that was passed in through the
+# $itk_option(-tabcommand) argument.
+#
+# This method is up for debate... do we need the -tabcommand option?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Notebook::_tabCommand { } {
+ global page$itk_component(hull)
+
+ if { $itk_option(-tabcommand) != {} } {
+ set newTabCmdStr $itk_option(-tabcommand)
+ lappend newTabCmdStr [set page$itk_component(hull)]
+
+ #eval $newTabCmdStr
+ uplevel #0 $newTabCmdStr
+ }
+}
+
+#
+# Page widget
+# ------------------------------------------------------------------
+#
+# The Page command creates a new window (given by the pathName argument)
+# and makes it into a Page widget. Additional options, described above
+# may be specified on the com mand line or in the option database to
+# configure aspects of the Page such as its back ground, cursor, and
+# geometry. The Page command returns its pathName argument. At the time
+# this command is invoked, there must not exist a window named pathName,
+# but path Name's parent must exist.
+#
+# A Page is a frame that holds a child site. It is nothing more than a
+# frame widget with some intelligence built in. Its primary purpose is
+# to support the Notebook's concept of a page. It allows another widget
+# like the Notebook to treat a page as a single object. The Page has an
+# associated label and knows how to return its child site.
+#
+# ------------------------------------------------------------------
+# AUTHOR: Bill W. Scott EMAIL: bscott@spd.dsccc.com
+#
+# ------------------------------------------------------------------
+# Copyright (c) 1995 DSC Communications Corp.
+# ======================================================================
+# Permission is hereby granted, without written agreement and without
+# license or royalty fees, to use, copy, modify, and distribute this
+# software and its documentation for any purpose, provided that the
+# above copyright notice and the following two paragraphs appear in
+# all copies of this software.
+#
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+# ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+# IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+# THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+# ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# ======================================================================
+#
+# Option database default resources:
+#
+option add *Page.disabledForeground #a3a3a3 widgetDefault
+option add *Page.label {} widgetDefault
+option add *Page.command {} widgetDefault
+
+itcl::class iwidgets::Page {
+ inherit itk::Widget
+
+ constructor {args} {}
+
+ itk_option define \
+ -disabledforeground disabledForeground DisabledForeground #a3a3a3
+ itk_option define -label label Label {}
+ itk_option define -command command Command {}
+
+ public method childsite { }
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Page::constructor {args} {
+ #
+ # Create the outermost frame to maintain geometry.
+ #
+ itk_component add cs {
+ frame $itk_interior.cs
+ } {
+ keep -cursor -background -width -height
+ }
+ pack $itk_component(cs) -fill both -expand yes
+ pack propagate $itk_component(cs) no
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+# ------------------------------------------------------------------
+# OPTION -disabledforeground
+#
+# Sets the disabledForeground color of this page
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Page::disabledforeground {
+}
+
+# ------------------------------------------------------------------
+# OPTION -label
+#
+# Sets the label of this page. The label is a string identifier
+# for this page.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Page::label {
+}
+
+# ------------------------------------------------------------------
+# OPTION -command
+#
+# The Tcl Command to associate with this page.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Page::command {
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Returns the child site widget of this page
+# ------------------------------------------------------------------
+itcl::body iwidgets::Page::childsite { } {
+ return $itk_component(cs)
+}
+
diff --git a/iwidgets/generic/optionmenu.itk b/iwidgets/generic/optionmenu.itk
new file mode 100644
index 00000000000..ddb3995fd41
--- /dev/null
+++ b/iwidgets/generic/optionmenu.itk
@@ -0,0 +1,664 @@
+#
+# Optionmenu
+# ----------------------------------------------------------------------
+# Implements an option menu widget with options to manage it.
+# An option menu displays a frame containing a label and a button.
+# A pop-up menu will allow for the value of the button to change.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Alfredo Jahn Phone: (214) 519-3545
+# Email: ajahn@spd.dsccc.com
+# alfredo@wn.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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.
+# ======================================================================
+
+#
+# Default resources.
+#
+
+option add *Optionmenu.highlightThickness 1 widgetDefault
+option add *Optionmenu.borderWidth 2 widgetDefault
+option add *Optionmenu.labelPos w widgetDefault
+option add *Optionmenu.labelMargin 2 widgetDefault
+option add *Optionmenu.popupCursor arrow widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Optionmenu {
+ keep -activebackground -activeborderwidth -activeforeground \
+ -background -borderwidth -cursor -disabledforeground -font \
+ -foreground -highlightcolor -highlightthickness -labelfont \
+ -popupcursor
+}
+
+# ------------------------------------------------------------------
+# OPTONMENU
+# ------------------------------------------------------------------
+itcl::class iwidgets::Optionmenu {
+ inherit iwidgets::Labeledwidget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -clicktime clickTime ClickTime 150
+ itk_option define -command command Command {}
+ itk_option define -cyclicon cyclicOn CyclicOn true
+ itk_option define -width width Width 0
+ itk_option define -font font Font -Adobe-Helvetica-Bold-R-Normal--*-120-*
+ itk_option define -borderwidth borderWidth BorderWidth 2
+ itk_option define -highlightthickness highlightThickness HighlightThickness 1
+ itk_option define -state state State normal
+
+ public {
+ method index {index}
+ method delete {first {last {}}}
+ method disable {index}
+ method enable {args}
+ method get {{first "current"} {last ""}}
+ method insert {index string args}
+ method popupMenu {args}
+ method select {index}
+ method sort {{mode "increasing"}}
+ }
+
+ protected {
+ variable _calcSize "" ;# non-null => _calcSize pending
+ }
+
+ private {
+ method _buttonRelease {time}
+ method _getNextItem {index}
+ method _next {}
+ method _postMenu {time}
+ method _previous {}
+ method _setItem {item}
+ method _setSize {{when later}}
+ method _setitems {items} ;# Set the list of menu entries
+
+ variable _postTime 0
+ variable _items {} ;# List of popup menu entries
+ variable _numitems 0 ;# List of popup menu entries
+
+ variable _currentItem "" ;# Active menu selection
+ }
+}
+
+#
+# Provide a lowercased access method for the Optionmenu class.
+#
+proc ::iwidgets::optionmenu {pathName args} {
+ uplevel ::iwidgets::Optionmenu $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::constructor {args} {
+ global tcl_platform
+
+ component hull configure -highlightthickness 0
+
+ itk_component add menuBtn {
+ menubutton $itk_interior.menuBtn -relief raised -indicatoron on \
+ -textvariable [itcl::scope _currentItem] -takefocus 1 \
+ -menu $itk_interior.menuBtn.menu
+ } {
+ usual
+ keep -borderwidth
+ if {$tcl_platform(platform) != "unix"} {
+ ignore -activebackground -activeforeground
+ }
+ }
+ pack $itk_interior.menuBtn -fill x
+ pack propagate $itk_interior no
+
+ itk_component add popupMenu {
+ menu $itk_interior.menuBtn.menu -tearoff no
+ } {
+ usual
+ ignore -tearoff
+ keep -activeborderwidth -borderwidth
+ rename -cursor -popupcursor popupCursor Cursor
+ }
+
+ #
+ # Bind to button release for all components.
+ #
+ bind $itk_component(menuBtn) <ButtonPress-1> \
+ "[itcl::code $this _postMenu %t]; break"
+ bind $itk_component(menuBtn) <KeyPress-space> \
+ "[itcl::code $this _postMenu %t]; break"
+ bind $itk_component(popupMenu) <ButtonRelease-1> \
+ [itcl::code $this _buttonRelease %t]
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::destructor {} {
+ if {$_calcSize != ""} {after cancel $_calcSize}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION -clicktime
+#
+# Interval time (in msec) used to determine that a single mouse
+# click has occurred. Used to post menu on a quick mouse click.
+# **WARNING** changing this value may cause the sigle-click
+# functionality to not work properly!
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Optionmenu::clicktime {}
+
+# ------------------------------------------------------------------
+# OPTION -command
+#
+# Specifies a command to be evaluated upon change in option menu.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Optionmenu::command {}
+
+# ------------------------------------------------------------------
+# OPTION -cyclicon
+#
+# Turns on/off the 3rd mouse button capability. This feature
+# allows the right mouse button to cycle through the popup
+# menu list without poping it up. <shift>M3 cycles through
+# the menu in reverse order.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Optionmenu::cyclicon {
+ if {$itk_option(-cyclicon)} {
+ bind $itk_component(menuBtn) <3> [itcl::code $this _next]
+ bind $itk_component(menuBtn) <Shift-3> [itcl::code $this _previous]
+ bind $itk_component(menuBtn) <KeyPress-Down> [itcl::code $this _next]
+ bind $itk_component(menuBtn) <KeyPress-Up> [itcl::code $this _previous]
+ } else {
+ bind $itk_component(menuBtn) <3> break
+ bind $itk_component(menuBtn) <Shift-3> break
+ bind $itk_component(menuBtn) <KeyPress-Down> break
+ bind $itk_component(menuBtn) <KeyPress-Up> break
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION -width
+#
+# Allows the menu label width to be set to a fixed size
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Optionmenu::width {
+ _setSize
+}
+
+# ------------------------------------------------------------------
+# OPTION -font
+#
+# Change all fonts for this widget. Also re-calculate height based
+# on font size (used to line up menu items over menu button label).
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Optionmenu::font {
+ _setSize
+}
+
+# ------------------------------------------------------------------
+# OPTION -borderwidth
+#
+# Change borderwidth for this widget. Also re-calculate height based
+# on font size (used to line up menu items over menu button label).
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Optionmenu::borderwidth {
+ _setSize
+}
+
+# ------------------------------------------------------------------
+# OPTION -highlightthickness
+#
+# Change highlightthickness for this widget. Also re-calculate
+# height based on font size (used to line up menu items over
+# menu button label).
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Optionmenu::highlightthickness {
+ _setSize
+}
+
+# ------------------------------------------------------------------
+# OPTION -state
+#
+# Specified one of two states for the Optionmenu: normal, or
+# disabled. If the Optionmenu is disabled, then option menu
+# selection is ignored.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Optionmenu::state {
+ switch $itk_option(-state) {
+ normal {
+ $itk_component(menuBtn) config -state normal
+ $itk_component(label) config -fg $itk_option(-foreground)
+ }
+ disabled {
+ $itk_component(menuBtn) config -state disabled
+ $itk_component(label) config -fg $itk_option(-disabledforeground)
+ }
+ default {
+ error "bad state option \"$itk_option(-state)\":\
+ should be disabled or normal"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: index index
+#
+# Return the numerical index corresponding to index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::index {index} {
+
+ if {[regexp {(^[0-9]+$)} $index]} {
+ set idx [$itk_component(popupMenu) index $index]
+
+ if {$idx == "none"} {
+ return 0
+ }
+ return [expr {$index > $idx ? $_numitems : $idx}]
+
+ } elseif {$index == "end"} {
+ return [expr {$_numitems - 1}]
+
+ } elseif {$index == "select"} {
+ return [lsearch $_items $_currentItem]
+
+ }
+
+ set numValue [lsearch -glob $_items $index]
+
+ if {$numValue == -1} {
+ error "bad Optionmenu index \"$index\""
+ }
+ return $numValue
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete first ?last?
+#
+# Remove an item (or range of items) from the popup menu.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::delete {first {last {}}} {
+
+ set first [index $first]
+ set last [expr {$last != {} ? [index $last] : $first}]
+ set nextAvail $_currentItem
+
+ #
+ # If current item is in delete range point to next available.
+ #
+ if {$_numitems > 1 &&
+ ([lsearch -exact [lrange $_items $first $last] [get]] != -1)} {
+ set nextAvail [_getNextItem $last]
+ }
+
+ _setitems [lreplace $_items $first $last]
+
+ #
+ # Make sure "nextAvail" is still in the list.
+ #
+ set index [lsearch -exact $_items $nextAvail]
+ _setItem [expr {$index != -1 ? $nextAvail : ""}]
+}
+
+# ------------------------------------------------------------------
+# METHOD: disable index
+#
+# Disable a menu item in the option menu. This will prevent the user
+# from being able to select this item from the menu. This only effects
+# the state of the item in the menu, in other words, should the item
+# be the currently selected item, the user is responsible for
+# determining this condition and taking appropriate action.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::disable {index} {
+ set index [index $index]
+ $itk_component(popupMenu) entryconfigure $index -state disabled
+}
+
+# ------------------------------------------------------------------
+# METHOD: enable index
+#
+# Enable a menu item in the option menu. This will allow the user
+# to select this item from the menu.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::enable {index} {
+ set index [index $index]
+ $itk_component(popupMenu) entryconfigure $index -state normal
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Returns the current menu item.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::get {{first "current"} {last ""}} {
+ if {"current" == $first} {
+ return $_currentItem
+ }
+
+ set first [index $first]
+ if {"" == $last} {
+ return [$itk_component(popupMenu) entrycget $first -label]
+ }
+
+ if {"end" == $last} {
+ set last [$itk_component(popupMenu) index end]
+ } else {
+ set last [index $last]
+ }
+ set rval ""
+ while {$first <= $last} {
+ lappend rval [$itk_component(popupMenu) entrycget $first -label]
+ incr first
+ }
+ return $rval
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert index string ?string?
+#
+# Insert an item in the popup menu.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::insert {index string args} {
+ if {$index == "end"} {
+ set index $_numitems
+ } else {
+ set index [index $index]
+ }
+ set args [linsert $args 0 $string]
+ _setitems [eval linsert {$_items} $index $args]
+ return ""
+}
+
+# ------------------------------------------------------------------
+# METHOD: select index
+#
+# Select an item from the popup menu to display on the menu label
+# button.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::select {index} {
+ set index [index $index]
+ if {$index > ($_numitems - 1)} {
+ incr index -1
+ }
+ _setItem [lindex $_items $index]
+}
+
+# ------------------------------------------------------------------
+# METHOD: popupMenu
+#
+# Evaluates the specified args against the popup menu component
+# and returns the result.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::popupMenu {args} {
+ return [eval $itk_component(popupMenu) $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: sort mode
+#
+# Sort the current menu in either "ascending" or "descending" order.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::sort {{mode "increasing"}} {
+ switch $mode {
+ ascending -
+ increasing {
+ _setitems [lsort -increasing $_items]
+ }
+ descending -
+ decreasing {
+ _setitems [lsort -decreasing $_items]
+ }
+ default {
+ error "bad sort argument \"$mode\": should be ascending,\
+ descending, increasing, or decreasing"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _buttonRelease
+#
+# Display the popup menu. Menu position is calculated.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::_buttonRelease {time} {
+ if {(abs([expr $_postTime - $time])) <= $itk_option(-clicktime)} {
+ return -code break
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _getNextItem index
+#
+# Allows either a string or index number to be passed in, and returns
+# the next item in the list in string format. Wrap around is automatic.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::_getNextItem {index} {
+
+ if {[incr index] >= $_numitems} {
+ set index 0 ;# wrap around
+ }
+ return [lindex $_items $index]
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _next
+#
+# Sets the current option label to next item in list if that item is
+# not disbaled.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::_next {} {
+ if {$itk_option(-state) != "normal"} {
+ return
+ }
+ set i [lsearch -exact $_items $_currentItem]
+
+ for {set cnt 0} {$cnt < $_numitems} {incr cnt} {
+
+ if {[incr i] >= $_numitems} {
+ set i 0
+ }
+
+ if {[$itk_component(popupMenu) entrycget $i -state] != "disabled"} {
+ _setItem [lindex $_items $i]
+ break
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _previous
+#
+# Sets the current option label to previous item in list if that
+# item is not disbaled.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::_previous {} {
+ if {$itk_option(-state) != "normal"} {
+ return
+ }
+
+ set i [lsearch -exact $_items $_currentItem]
+
+ for {set cnt 0} {$cnt < $_numitems} {incr cnt} {
+ set i [expr {$i - 1}]
+
+ if {$i < 0} {
+ set i [expr {$_numitems - 1}]
+ }
+
+ if {[$itk_component(popupMenu) entrycget $i -state] != "disabled"} {
+ _setItem [lindex $_items $i]
+ break
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _postMenu time
+#
+# Display the popup menu. Menu position is calculated.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::_postMenu {time} {
+ #
+ # Don't bother to post if menu is empty.
+ #
+ if {[llength $_items] > 0 && $itk_option(-state) == "normal"} {
+ set _postTime $time
+ set itemIndex [lsearch -exact $_items $_currentItem]
+
+ set margin [expr {$itk_option(-borderwidth) \
+ + $itk_option(-highlightthickness)}]
+
+ set x [expr {[winfo rootx $itk_component(menuBtn)] + $margin}]
+ set y [expr {[winfo rooty $itk_component(menuBtn)] \
+ - [$itk_component(popupMenu) yposition $itemIndex] + $margin}]
+
+ tk_popup $itk_component(popupMenu) $x $y
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setItem
+#
+# Set the menu button label to item, then dismiss the popup menu.
+# Also check if item has been changed. If so, also call user-supplied
+# command.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::_setItem {item} {
+ if {$_currentItem != $item} {
+ set _currentItem $item
+ if {[winfo ismapped $itk_component(hull)]} {
+ uplevel #0 $itk_option(-command)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setitems items
+#
+# Create a list of items available on the menu. Used to create the
+# popup menu.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::_setitems {items_} {
+
+ #
+ # Delete the old menu entries, and set the new list of
+ # menu entries to those specified in "items_".
+ #
+ $itk_component(popupMenu) delete 0 last
+ set _items ""
+ set _numitems [llength $items_]
+
+ #
+ # Clear the menu button label.
+ #
+ if {$_numitems == 0} {
+ _setItem ""
+ return
+ }
+
+ set savedCurrentItem $_currentItem
+
+ foreach opt $items_ {
+ lappend _items $opt
+ $itk_component(popupMenu) add command -label $opt \
+ -command [itcl::code $this _setItem $opt]
+ }
+ set first [lindex $_items 0]
+
+ #
+ # Make sure "savedCurrentItem" is still in the list.
+ #
+ if {$first != ""} {
+ set i [lsearch -exact $_items $savedCurrentItem]
+ #-------------------------------------------------------------
+ # BEGIN BUG FIX: csmith (Chad Smith: csmith@adc.com), 11/18/99
+ #-------------------------------------------------------------
+ # The previous code fragment:
+ # <select [expr {$i != -1 ? $savedCurrentItem : $first}]>
+ # is faulty because of exponential numbers. For example,
+ # 2e-4 is numerically equal to 2e-04, but the string representation
+ # is of course different. As a result, the select invocation
+ # fails, and an error message is printed.
+ #-------------------------------------------------------------
+ if {$i != -1} {
+ select $savedCurrentItem
+ } else {
+ select $first
+ }
+ #-------------------------------------------------------------
+ # END BUG FIX
+ #-------------------------------------------------------------
+ } else {
+ _setItem ""
+ }
+
+ _setSize
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setSize ?when?
+#
+# Set the size of the option menu. If "when" is "now", the change
+# is applied immediately. If it is "later" or it is not specified,
+# then the change is applied later, when the application is idle.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Optionmenu::_setSize {{when later}} {
+
+ if {$when == "later"} {
+ if {$_calcSize == ""} {
+ set _calcSize [after idle [itcl::code $this _setSize now]]
+ }
+ return
+ }
+
+ set margin [expr {2*($itk_option(-borderwidth) \
+ + $itk_option(-highlightthickness))}]
+
+ if {"0" != $itk_option(-width)} {
+ set width $itk_option(-width)
+ } else {
+ set width [expr {[winfo reqwidth $itk_component(popupMenu)]+$margin+20}]
+ }
+ set height [winfo reqheight $itk_component(menuBtn)]
+ $itk_component(lwchildsite) configure -width $width -height $height
+
+ set _calcSize ""
+}
diff --git a/iwidgets/generic/pane.itk b/iwidgets/generic/pane.itk
new file mode 100644
index 00000000000..fe93a1c08c1
--- /dev/null
+++ b/iwidgets/generic/pane.itk
@@ -0,0 +1,128 @@
+#
+# Paned
+# ----------------------------------------------------------------------
+# Implements a pane for a paned window widget. The pane is itself a
+# frame with a child site for other widgets. The pane class performs
+# basic option management.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Pane {
+ keep -background -cursor
+}
+
+# ------------------------------------------------------------------
+# PANE
+# ------------------------------------------------------------------
+itcl::class iwidgets::Pane {
+ inherit itk::Widget
+
+ constructor {args} {}
+
+ itk_option define -minimum minimum Minimum 10
+ itk_option define -margin margin Margin 8
+
+ public method childSite {} {}
+}
+
+#
+# Provide a lowercased access method for the Pane class.
+#
+proc ::iwidgets::pane {pathName args} {
+ uplevel ::iwidgets::Pane $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Pane::constructor {args} {
+ #
+ # Create the pane childsite.
+ #
+ itk_component add childsite {
+ frame $itk_interior.childsite
+ } {
+ keep -background -cursor
+ }
+ pack $itk_component(childsite) -fill both -expand yes
+
+ #
+ # Set the itk_interior variable to be the childsite for derived
+ # classes.
+ #
+ set itk_interior $itk_component(childsite)
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -minimum
+#
+# Specifies the minimum size that the pane may reach.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pane::minimum {
+ set pixels \
+ [winfo pixels $itk_component(hull) $itk_option(-minimum)]
+
+ set itk_option(-minimum) $pixels
+}
+
+# ------------------------------------------------------------------
+# OPTION: -margin
+#
+# Specifies the border distance between the pane and pane contents.
+# This is done by setting the borderwidth of the pane to the margin.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pane::margin {
+ set pixels [winfo pixels $itk_component(hull) $itk_option(-margin)]
+ set itk_option(-margin) $pixels
+
+ $itk_component(childsite) configure \
+ -borderwidth $itk_option(-margin)
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childSite
+#
+# Return the pane child site path name.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Pane::childSite {} {
+ return $itk_component(childsite)
+}
diff --git a/iwidgets/generic/panedwindow.itk b/iwidgets/generic/panedwindow.itk
new file mode 100644
index 00000000000..180ead43a24
--- /dev/null
+++ b/iwidgets/generic/panedwindow.itk
@@ -0,0 +1,942 @@
+#
+# Panedwindow
+# ----------------------------------------------------------------------
+# Implements a multiple paned window widget capable of orienting the panes
+# either vertically or horizontally. Each pane is itself a frame acting
+# as a child site for other widgets. The border separating each pane
+# contains a sash which allows user positioning of the panes relative to
+# one another.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Panedwindow {
+ keep -background -cursor -sashcursor
+}
+
+# ------------------------------------------------------------------
+# PANEDWINDOW
+# ------------------------------------------------------------------
+itcl::class iwidgets::Panedwindow {
+ inherit itk::Widget
+
+ constructor {args} {}
+
+ itk_option define -orient orient Orient horizontal
+ itk_option define -sashborderwidth sashBorderWidth SashBorderWidth 2
+ itk_option define -sashcursor sashCursor SashCursor crosshair
+ itk_option define -sashwidth sashWidth SashWidth 10
+ itk_option define -sashheight sashHeight SashHeight 10
+ itk_option define -thickness thickness Thickness 3
+ itk_option define -sashindent sashIndent SashIndent -10
+ itk_option define -showhandle showHandle ShowHandle 1
+
+ public method index {index}
+ public method childsite {args}
+ public method fraction {args}
+ public method add {tag args}
+ public method insert {index tag args}
+ public method delete {index}
+ public method hide {index}
+ public method show {index}
+ public method paneconfigure {index args}
+ public method reset {}
+
+ protected method _pwConfigureEventHandler {width height}
+ protected method _startGrip {where num}
+ protected method _endGrip {where num}
+ protected method _configGrip {where num}
+ protected method _handleGrip {where num}
+ protected method _moveSash {where num}
+
+ private method _setFracArray {}
+ private method _setActivePanes {}
+ private method _calcFraction {where num}
+ private method _makeSashes {}
+ private method _placeSash {i}
+ private method _placePanes {{start 0} {end end}}
+
+ private variable _initialized 0 ;# Denotes initialized state.
+ private variable _panes {} ;# List of panes.
+ private variable _activePanes {} ;# List of active panes.
+ private variable _sashes {} ;# List of sashes.
+ private variable _separators {} ;# List of separators.
+ private variable _frac ;# Array of fraction percentages.
+ private variable _lowerlimit ;# Margin distance above/left of sash.
+ private variable _upperlimit ;# Margin distance below/right of sash.
+ private variable _dimension ;# Width/Height at start of drag.
+ private variable _sashloc ;# Array of dist of sash from above/left.
+ private variable _pixels ;# Array of dist of sash from above/left.
+ private variable _minheight ;# Array of min heights for panes.
+ private variable _minsashmoved ;# Lowest sash moved during dragging.
+ private variable _maxsashmoved ;# Highest sash moved during dragging.
+ private variable _dragging 0 ;# Boolean for dragging enabled.
+ private variable _movecount 0 ;# Kludge counter to get sashes to
+ ;# display without calling update
+ ;# idletasks too often.
+ private variable _width 0 ;# hull's width.
+ private variable _height 0 ;# hull's height.
+ private variable _unique -1 ;# Unique number for pane names.
+
+ private variable _relief ;# relief for -showhandle
+}
+
+#
+# Provide a lowercased access method for the Panedwindow class.
+#
+proc ::iwidgets::panedwindow {pathName args} {
+ uplevel ::iwidgets::Panedwindow $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Panedwindow.width 10 widgetDefault
+option add *Panedwindow.height 10 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::constructor {args} {
+ itk_option add hull.width hull.height
+
+ pack propagate $itk_component(hull) no
+
+ #
+ # Add binding for the configure event.
+ #
+ bind pw-config-$this <Configure> [itcl::code $this _pwConfigureEventHandler %w %h]
+ bindtags $itk_component(hull) \
+ [linsert [bindtags $itk_component(hull)] 0 pw-config-$this]
+
+ array set _relief {0 sunken 1 raised}
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -orient
+#
+# Specifies the orientation of the sashes. Once the paned window
+# has been mapped, set the sash bindings and place the panes.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Panedwindow::orient {
+ if {$_initialized} {
+ switch $itk_option(-orient) {
+ vertical {
+ for {set i 1} {$i < [llength $_activePanes]} {incr i} {
+ bind $itk_component(sash$i) <Button-1> \
+ [itcl::code $this _startGrip %x $i]
+ bind $itk_component(sash$i) <B1-Motion> \
+ [itcl::code $this _handleGrip %x $i]
+ bind $itk_component(sash$i) <B1-ButtonRelease-1> \
+ [itcl::code $this _endGrip %x $i]
+ bind $itk_component(sash$i) <Configure> \
+ [itcl::code $this _configGrip %x $i]
+ }
+
+ _setFracArray
+ _makeSashes
+ _placePanes
+ }
+
+ horizontal {
+ for {set i 1} {$i < [llength $_activePanes]} {incr i} {
+ bind $itk_component(sash$i) <Button-1> \
+ [itcl::code $this _startGrip %y $i]
+ bind $itk_component(sash$i) <B1-Motion> \
+ [itcl::code $this _handleGrip %y $i]
+ bind $itk_component(sash$i) <B1-ButtonRelease-1> \
+ [itcl::code $this _endGrip %y $i]
+ bind $itk_component(sash$i) <Configure> \
+ [itcl::code $this _configGrip %y $i]
+ }
+
+ _setFracArray
+ _makeSashes
+ _placePanes
+ }
+
+ default {
+ error "bad orientation option \"$itk_option(-orient)\":\
+ should be horizontal or vertical"
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -sashborderwidth
+#
+# Specifies a non-negative value indicating the width of the 3-D
+# border to draw around the outside of the sash.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Panedwindow::sashborderwidth {
+ set pixels [winfo pixels $itk_component(hull) \
+ $itk_option(-sashborderwidth)]
+ set itk_option(-sashborderwidth) $pixels
+
+ if {$_initialized} {
+ for {set i 1} {$i < [llength $_activePanes]} {incr i} {
+ $itk_component(sash$i) configure \
+ -borderwidth $itk_option(-sashborderwidth)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -sashcursor
+#
+# Specifies the type of cursor to be used when over the sash.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Panedwindow::sashcursor {
+ if {$_initialized} {
+ for {set i 1} {$i < [llength $_activePanes]} {incr i} {
+ $itk_component(sash$i) configure -cursor $itk_option(-sashcursor)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -sashwidth
+#
+# Specifies the width of the sash.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Panedwindow::sashwidth {
+ set pixels [winfo pixels $itk_component(hull) \
+ $itk_option(-sashwidth)]
+ set itk_option(-sashwidth) $pixels
+
+ if {$_initialized} {
+ for {set i 1} {$i < [llength $_activePanes]} {incr i} {
+ $itk_component(sash$i) configure \
+ -width $itk_option(-sashwidth)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -sashheight
+#
+# Specifies the height of the sash,
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Panedwindow::sashheight {
+ set pixels [winfo pixels $itk_component(hull) \
+ $itk_option(-sashheight)]
+ set itk_option(-sashheight) $pixels
+
+ if {$_initialized} {
+ for {set i 1} {$i < [llength $_activePanes]} {incr i} {
+ $itk_component(sash$i) configure \
+ -height $itk_option(-sashheight)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -showhandle
+#
+# Specifies whether or not to show the sash handle. If not, then the
+# whole separator becomes the handle. Valid values are 0 or 1.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Panedwindow::showhandle {
+ switch $itk_option(-showhandle) {
+ 0 - 1 {
+ # Update the sashes.
+ _makeSashes
+ _placePanes
+ }
+ default {
+ error "Invalid option for -showhandle: $itk_option(-showhandle).\
+ Must be 1 or 0."
+ }
+ }
+}
+
+
+# ------------------------------------------------------------------
+# OPTION: -thickness
+#
+# Specifies the thickness of the separators. It sets the width and
+# height of the separator to the thickness value and the borderwidth
+# to half the thickness.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Panedwindow::thickness {
+ set pixels [winfo pixels $itk_component(hull) \
+ $itk_option(-thickness)]
+ set itk_option(-thickness) $pixels
+
+ if {$_initialized} {
+ for {set i 1} {$i < [llength $_activePanes]} {incr i} {
+ $itk_component(separator$i) configure \
+ -height $itk_option(-thickness)
+ $itk_component(separator$i) configure \
+ -width $itk_option(-thickness)
+ $itk_component(separator$i) configure \
+ -borderwidth [expr {$itk_option(-thickness) / 2}]
+ }
+
+ for {set i 1} {$i < [llength $_activePanes]} {incr i} {
+ _placeSash $i
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -sashindent
+#
+# Specifies the placement of the sash along the panes. A positive
+# value causes the sash to be offset from the near (left/top) side
+# of the pane, and a negative value causes the sash to be offset from
+# the far (right/bottom) side. If the offset is greater than the
+# width, then the sash is placed flush against the side.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Panedwindow::sashindent {
+ set pixels [winfo pixels $itk_component(hull) \
+ $itk_option(-sashindent)]
+ set itk_option(-sashindent) $pixels
+
+ if {$_initialized} {
+ for {set i 1} {$i < [llength $_activePanes]} {incr i} {
+ _placeSash $i
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: index index
+#
+# Searches the panes in the paned window for the one with the
+# requested tag, numerical index, or keyword "end". Returns the pane's
+# numerical index if found, otherwise error.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::index {index} {
+ if {[llength $_panes] > 0} {
+ if {[regexp {(^[0-9]+$)} $index]} {
+ if {$index < [llength $_panes]} {
+ return $index
+ } else {
+ error "Panedwindow index \"$index\" is out of range"
+ }
+
+ } elseif {$index == "end"} {
+ return [expr {[llength $_panes] - 1}]
+
+ } else {
+ if {[set idx [lsearch $_panes $index]] != -1} {
+ return $idx
+ }
+
+ error "bad Panedwindow index \"$index\": must be number, end,\
+ or pattern"
+ }
+
+ } else {
+ error "Panedwindow \"$itk_component(hull)\" has no panes"
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: childsite ?index?
+#
+# Given an index return the specifc childsite path name. Invoked
+# without an index return a list of all the child site panes. The
+# list is ordered from the near side (left/top).
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::childsite {args} {
+ if {! $_initialized} {
+ set _initialized 1
+ reset
+ }
+
+ if {[llength $args] == 0} {
+ set children {}
+
+ foreach pane $_panes {
+ lappend children [$itk_component($pane) childSite]
+ }
+
+ return $children
+
+ } else {
+ set index [index [lindex $args 0]]
+ return [$itk_component([lindex $_panes $index]) childSite]
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: fraction percentage percentage ?percentage ...?
+#
+# Sets the visible percentage of the panes. Specifies a list of
+# percentages which are applied to the currently visible panes from
+# the near side (left/top). The number of percentages must be equal
+# to the current number of visible (mapped) panes and add up to 100.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::fraction {args} {
+ #set args [linsert $args 0 $percentage1 $percentage2]
+
+
+ if {[llength $args] == [llength $_activePanes]} {
+ set sum 0
+
+ for {set i 0} {$i < [llength $args]} {incr i} {
+ set sum [expr {$sum + [lindex $args $i]}]
+ }
+
+ if {$sum == 100} {
+ set perc 0.0
+
+ for {set i 0} {$i < [llength $_activePanes]} {incr i} {
+ set _frac($i) $perc
+ set perc [expr {$perc + [expr {[lindex $args $i] / 100.0}]}]
+ }
+
+ set _frac($i) 1.0
+
+ if {[winfo ismapped $itk_component(hull)]} {
+ _placePanes
+ }
+
+ } else {
+ error "bad fraction arguments \"$args\": they should add\
+ up to 100"
+ }
+
+ } elseif {[llength $args] == 0} {
+
+ for {set i 0; set j 1} {$j < [llength $_activePanes]} {incr i; incr j} {
+ lappend _ret [expr {round(($_frac($j) - $_frac($i))*100)}]
+ }
+ lappend _ret [eval expr {100 - ([join $_ret +])}]
+
+ return $_ret
+ } else {
+ error "wrong # args: should be \"$itk_component(hull)\
+ fraction percentage percentage ?percentage ...?\",\
+ where the number of percentages is\
+ [llength $_activePanes] and equal 100
+ or \"$itk_component(hull) fraction\"
+ which will return a list of the current percentages"
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: add tag ?option value option value ...?
+#
+# Add a new pane to the paned window to the far (right/bottom) side.
+# The method takes additional options which are passed on to the
+# pane constructor. These include -margin, and -minimum. The path
+# of the pane is returned.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::add {tag args} {
+ #
+ # Create panes.
+ #
+ itk_component add $tag {
+ eval iwidgets::Pane $itk_interior.pane[incr _unique] $args
+ } {
+ keep -background -cursor
+ }
+
+ lappend _panes $tag
+ lappend _activePanes $tag
+
+ reset
+
+ return $itk_component($tag)
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert index tag ?option value option value ...?
+#
+# Insert the specified pane in the paned window just before the one
+# given by index. Any additional options which are passed on to the
+# pane constructor. These include -margin, -minimum. The path of
+# the pane is returned.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::insert {index tag args} {
+ #
+ # Create panes.
+ #
+ itk_component add $tag {
+ eval iwidgets::Pane $itk_interior.pane[incr _unique] $args
+ } {
+ keep -background -cursor
+ }
+
+ set index [index $index]
+ set _panes [linsert $_panes $index $tag]
+ lappend _activePanes $tag
+
+ reset
+
+ return $itk_component($tag)
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete index
+#
+# Delete the specified pane.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::delete {index} {
+ set index [index $index]
+ set tag [lindex $_panes $index]
+
+ destroy $itk_component($tag)
+
+ set _panes [lreplace $_panes $index $index]
+
+ reset
+}
+
+# ------------------------------------------------------------------
+# METHOD: hide index
+#
+# Remove the specified pane from the paned window.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::hide {index} {
+ set index [index $index]
+ set tag [lindex $_panes $index]
+
+ if {[set idx [lsearch -exact $_activePanes $tag]] != -1} {
+ set _activePanes [lreplace $_activePanes $idx $idx]
+ }
+
+ reset
+}
+
+# ------------------------------------------------------------------
+# METHOD: show index
+#
+# Display the specified pane in the paned window.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::show {index} {
+ set index [index $index]
+ set tag [lindex $_panes $index]
+
+ if {[lsearch -exact $_activePanes $tag] == -1} {
+ lappend _activePanes $tag
+ }
+
+ reset
+}
+
+# ------------------------------------------------------------------
+# METHOD: paneconfigure index ?option? ?value option value ...?
+#
+# Configure a specified pane. This method allows configuration of
+# panes from the Panedwindow level. The options may have any of the
+# values accepted by the add method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::paneconfigure {index args} {
+ set index [index $index]
+ set tag [lindex $_panes $index]
+
+ return [uplevel $itk_component($tag) configure $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: reset
+#
+# Redisplay the panes based on the default percentages of the panes.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::reset {} {
+ if {$_initialized && [llength $_panes]} {
+ _setActivePanes
+ _setFracArray
+
+ _makeSashes
+ _placePanes
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _pwConfigureEventHandler
+#
+# Performs operations necessary following a configure event. This
+# includes placing the panes.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_pwConfigureEventHandler {width height} {
+ set _width $width
+ set _height $height
+ if {$_initialized} {
+ _placePanes
+ } else {
+ set _initialized 1
+ reset
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _startGrip where num
+#
+# Starts the sash drag and drop operation. At the start of the drag
+# operation all the information is known as for the upper and lower
+# limits for sash movement. The calculation is made at this time and
+# stored in protected variables for later access during the drag
+# handling routines.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_startGrip {where num} {
+ if {$itk_option(-orient) == "horizontal"} {
+ set _dimension $_height
+ } else {
+ set _dimension $_width
+ }
+
+ set _minsashmoved $num
+ set _maxsashmoved $num
+ set totMinHeight 0
+ set cnt [llength $_activePanes]
+ set _sashloc(0) 0
+ set _pixels($cnt) [expr {int($_dimension)}]
+ for {set i 0} {$i < $cnt} {incr i} {
+ set _pixels($i) [expr {int($_frac($i) * $_dimension)}]
+ set margaft [$itk_component([lindex $_activePanes $i]) cget -margin]
+ set minaft [$itk_component([lindex $_activePanes $i]) cget -minimum]
+ set _minheight($i) [expr {$minaft + (2 * $margaft)}]
+ incr totMinHeight $_minheight($i)
+ }
+ set _dragging [expr {$_dimension > $totMinHeight}]
+
+ grab $itk_component(sash$num)
+ raise $itk_component(separator$num)
+ raise $itk_component(sash$num)
+
+ $itk_component(sash$num) configure -relief sunken
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _endGrip where num
+#
+# Ends the sash drag and drop operation.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_endGrip {where num} {
+ $itk_component(sash$num) configure -relief $_relief($itk_option(-showhandle))
+ grab release $itk_component(sash$num)
+ if {$_dragging} {
+ _calcFraction [expr {$_sashloc($num) + $where}] $num
+ _placePanes [expr {$_minsashmoved - 1}] $_maxsashmoved
+ set _dragging 0
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _configGrip where num
+#
+# Configure action for sash.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_configGrip {where num} {
+ set _sashloc($num) $where
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _handleGrip where num
+#
+# Motion action for sash.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_handleGrip {where num} {
+ if {$_dragging} {
+ _moveSash [expr {$where + $_sashloc($num)}] $num
+ incr _movecount
+ if {$_movecount>4} {
+ set _movecount 0
+ update idletasks
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _moveSash where num
+#
+# Move the sash to the absolute pixel location
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_moveSash {where num} {
+ set _minsashmoved [expr {($_minsashmoved<$num)?$_minsashmoved:$num}]
+ set _maxsashmoved [expr {($_maxsashmoved>$num)?$_maxsashmoved:$num}]
+ set oldfrac $_frac($num)
+ _calcFraction $where $num
+ if {$_frac($num)!=$oldfrac} { _placeSash $num }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setFracArray
+#
+# Calculates the percentages for the fraction array which lists the
+# percentages for each pane.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_setFracArray {} {
+ set perc 0.0
+ if {[llength $_activePanes] != 0} {
+ set percIncr [expr {1.0 / [llength $_activePanes]}]
+ }
+
+ for {set i 0} {$i < [llength $_activePanes]} {incr i} {
+ set _frac($i) $perc
+ set perc [expr {$perc + $percIncr}]
+ }
+
+ set _frac($i) 1.0
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setActivePanes
+#
+# Resets the active pane list.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_setActivePanes {} {
+ set _prevActivePanes $_activePanes
+
+ set _activePanes {}
+
+ foreach pane $_panes {
+ if {[lsearch -exact $_prevActivePanes $pane] != -1} {
+ lappend _activePanes $pane
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _calcFraction where num
+#
+# Determines the fraction for the sash. Make sure the fraction does
+# not go past the minimum for the pane on each side of the separator.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_calcFraction {where num} {
+
+ set numi [expr {$num + 1}]
+ set numd [expr {$num - 1}]
+
+ set _lowerlimit [expr {$_pixels($numd) + $_minheight($numd)}]
+ set _upperlimit [expr {$_pixels($numi) - $_minheight($num)}]
+
+ set dir [expr {$where - $_pixels($num)}]
+
+ if {$where < $_lowerlimit && $dir <= 0} {
+ if {$num == 1} {
+ set _pixels($num) $_lowerlimit
+ } {
+ _moveSash [expr {$where - $_minheight($numd)}] $numd
+ set _pixels($num) [expr {$_pixels($numd) + $_minheight($numd)}]
+ }
+ } elseif {$where > $_upperlimit && $dir >= 0} {
+ if {$numi == [llength $_activePanes]} {
+ set _pixels($num) $_upperlimit
+ } {
+ _moveSash [expr {$where + $_minheight($num)}] $numi
+ set _pixels($num) \
+ [expr {$_pixels($numi) - $_minheight($num)}]
+ }
+ } else {
+ set _pixels($num) $where
+ }
+ set _frac($num) [expr $_pixels($num).0 / $_dimension]
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _makeSashes
+#
+# Removes any previous sashes and separators and creates new one.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_makeSashes {} {
+ #
+ # Remove any existing sashes and separators.
+ #
+ foreach sash $_sashes {
+ destroy $itk_component($sash)
+ }
+
+ foreach separator $_separators {
+ destroy $itk_component($separator)
+ }
+
+ set _sashes {}
+ set _separators {}
+
+ #
+ # Create one less separator and sash than the number of panes.
+ #
+ for {set id 1} {$id < [llength $_activePanes]} {incr id} {
+ itk_component add sash$id {
+ frame $itk_interior.sash$id -relief $_relief($itk_option(-showhandle)) \
+ -borderwidth $itk_option(-sashborderwidth) \
+ -cursor $itk_option(-sashcursor) \
+ -width $itk_option(-sashwidth) \
+ -height $itk_option(-sashheight)
+ } {
+ keep -background
+ }
+
+ lappend _sashes sash$id
+
+ switch $itk_option(-orient) {
+ vertical {
+ bind $itk_component(sash$id) <Button-1> \
+ [itcl::code $this _startGrip %x $id]
+ bind $itk_component(sash$id) <B1-Motion> \
+ [itcl::code $this _handleGrip %x $id]
+ bind $itk_component(sash$id) <B1-ButtonRelease-1> \
+ [itcl::code $this _endGrip %x $id]
+ bind $itk_component(sash$id) <Configure> \
+ [itcl::code $this _configGrip %x $id]
+ }
+
+ horizontal {
+ bind $itk_component(sash$id) <Button-1> \
+ [itcl::code $this _startGrip %y $id]
+ bind $itk_component(sash$id) <B1-Motion> \
+ [itcl::code $this _handleGrip %y $id]
+ bind $itk_component(sash$id) <B1-ButtonRelease-1> \
+ [itcl::code $this _endGrip %y $id]
+ bind $itk_component(sash$id) <Configure> \
+ [itcl::code $this _configGrip %y $id]
+ }
+ }
+
+ itk_component add separator$id {
+ frame $itk_interior.separator$id -relief sunken \
+ -height $itk_option(-thickness) \
+ -width $itk_option(-thickness) \
+ -borderwidth [expr {$itk_option(-thickness) / 2}]
+ } {
+ keep -background -cursor
+ }
+
+ lappend _separators separator$id
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _placeSash i
+#
+# Places the position of the sash and separator.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_placeSash {i} {
+ if {$itk_option(-orient) == "horizontal"} {
+ place $itk_component(separator$i) -in $itk_component(hull) \
+ -x 0 -relwidth 1 -rely $_frac($i) -anchor w \
+ -height $itk_option(-thickness)
+
+ if {$itk_option(-sashindent) < 0} {
+ set sashPos [expr {$_width + $itk_option(-sashindent)}]
+ set sashAnchor e
+ } else {
+ set sashPos $itk_option(-sashindent)
+ set sashAnchor w
+ }
+
+ if {$itk_option(-showhandle)} {
+ place $itk_component(sash$i) -in $itk_component(hull) \
+ -x $sashPos -rely $_frac($i) -anchor $sashAnchor
+ } else {
+ place $itk_component(sash$i) -in $itk_component(hull) \
+ -x 0 -relwidth 1 -rely $_frac($i) -anchor w \
+ -height $itk_option(-thickness)
+ }
+
+ } else {
+ place $itk_component(separator$i) -in $itk_component(hull) \
+ -y 0 -relheight 1 -relx $_frac($i) -anchor n \
+ -width $itk_option(-thickness)
+
+ if {$itk_option(-sashindent) < 0} {
+ set sashPos [expr {$_height + $itk_option(-sashindent)}]
+ set sashAnchor s
+ } else {
+ set sashPos $itk_option(-sashindent)
+ set sashAnchor n
+ }
+
+ if {$itk_option(-showhandle)} {
+
+ place $itk_component(sash$i) -in $itk_component(hull) \
+ -y $sashPos -relx $_frac($i) -anchor $sashAnchor
+ } else {
+ place $itk_component(sash$i) -in $itk_component(hull) \
+ -y 0 -relheight 1 -relx $_frac($i) -anchor n \
+ -width $itk_option(-thickness)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _placePanes
+#
+# Resets the panes of the window following movement of the sash.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Panedwindow::_placePanes {{start 0} {end end}} {
+ if {$end=="end"} { set end [expr {[llength $_activePanes] - 1}] }
+ set _updatePanes [lrange $_activePanes $start $end]
+ if {$_updatePanes == $_activePanes} {
+ set _forgetPanes $_panes
+ } {
+ set _forgetPanes $_updatePanes
+ }
+ foreach pane $_forgetPanes {
+ place forget $itk_component($pane)
+ }
+
+
+ if {$itk_option(-orient) == "horizontal"} {
+ set i $start
+ foreach pane $_updatePanes {
+ place $itk_component($pane) -in $itk_component(hull) \
+ -x 0 -rely $_frac($i) -relwidth 1 \
+ -relheight [expr {$_frac([expr {$i + 1}]) - $_frac($i)}]
+ incr i
+ }
+
+ } else {
+ set i $start
+ foreach pane $_updatePanes {
+ place $itk_component($pane) -in $itk_component(hull) \
+ -y 0 -relx $_frac($i) -relheight 1 \
+ -relwidth [expr {$_frac([expr {$i + 1}]) - $_frac($i)}]
+ incr i
+ }
+
+ }
+
+ for {set i [expr {$start+1}]} {$i <= $end} {incr i} {
+ if {[array names itk_component separator$i] != ""} {
+ _placeSash $i
+ raise $itk_component(separator$i)
+ raise $itk_component(sash$i)
+ }
+ }
+}
diff --git a/iwidgets/generic/promptdialog.itk b/iwidgets/generic/promptdialog.itk
new file mode 100644
index 00000000000..9588eca8bd9
--- /dev/null
+++ b/iwidgets/generic/promptdialog.itk
@@ -0,0 +1,199 @@
+#
+# Promptdialog
+# ----------------------------------------------------------------------
+# Implements a prompt dialog similar to the OSF/Motif standard prompt
+# dialog composite widget. The Promptdialog is derived from the
+# Dialog class and is composed of a EntryField with methods to
+# manipulate the dialog buttons.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Promptdialog {
+ keep -background -borderwidth -cursor -foreground -highlightcolor \
+ -highlightthickness -insertbackground -insertborderwidth \
+ -insertofftime -insertontime -insertwidth -labelfont -modality \
+ -selectbackground -selectborderwidth -selectforeground \
+ -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# PROMPTDIALOG
+# ------------------------------------------------------------------
+itcl::class iwidgets::Promptdialog {
+ inherit iwidgets::Dialog
+
+ constructor {args} {}
+
+ public method get {}
+ public method clear {}
+ public method insert {args}
+ public method delete {args}
+ public method icursor {args}
+ public method index {args}
+ public method scan {args}
+ public method selection {args}
+ method xview {args}
+}
+
+#
+# Provide a lowercased access method for the Dialogshell class.
+#
+proc ::iwidgets::promptdialog {pathName args} {
+ uplevel ::iwidgets::Promptdialog $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Promptdialog.labelText Selection widgetDefault
+option add *Promptdialog.labelPos nw widgetDefault
+option add *Promptdialog.title "Prompt Dialog" widgetDefault
+option add *Promptdialog.master "." widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::constructor {args} {
+ #
+ # Set the borderwidth to zero.
+ #
+ component hull configure -borderwidth 0
+
+ #
+ # Create an entry field widget.
+ #
+ itk_component add prompt {
+ iwidgets::Entryfield $itk_interior.prompt -command [itcl::code $this invoke]
+ } {
+ usual
+
+ keep -exportselection -invalid -labelpos -labeltext -relief \
+ -show -textbackground -textfont -validate
+ }
+
+ pack $itk_component(prompt) -fill x -expand yes
+ set itk_interior [childsite]
+
+ hide Help
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Thinwrapped method of entry field class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::get {} {
+ return [$itk_component(prompt) get]
+}
+
+# ------------------------------------------------------------------
+# METHOD: clear
+#
+# Thinwrapped method of entry field class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::clear {} {
+ eval $itk_component(prompt) clear
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert args
+#
+# Thinwrapped method of entry field class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::insert {args} {
+ eval $itk_component(prompt) insert $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete first ?last?
+#
+# Thinwrapped method of entry field class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::delete {args} {
+ eval $itk_component(prompt) delete $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: icursor
+#
+# Thinwrapped method of entry field class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::icursor {args} {
+ eval $itk_component(prompt) icursor $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: index
+#
+# Thinwrapped method of entry field class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::index {args} {
+ return [eval $itk_component(prompt) index $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: scan option args
+#
+# Thinwrapped method of entry field class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::scan {args} {
+ eval $itk_component(prompt) scan $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: selection args
+#
+# Thinwrapped method of entry field class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::selection {args} {
+ eval $itk_component(prompt) selection $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: xview args
+#
+# Thinwrapped method of entry field class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Promptdialog::xview {args} {
+ eval $itk_component(prompt) xview $args
+}
+
+
diff --git a/iwidgets/generic/pushbutton.itk b/iwidgets/generic/pushbutton.itk
new file mode 100644
index 00000000000..31a5102fa09
--- /dev/null
+++ b/iwidgets/generic/pushbutton.itk
@@ -0,0 +1,356 @@
+#
+# Pushbutton
+# ----------------------------------------------------------------------
+# Implements a Motif-like Pushbutton with an optional default ring.
+#
+# WISH LIST:
+# 1) Allow bitmaps and text on the same button face (Tk limitation).
+# 2) provide arm and disarm bitmaps.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+# Bret A. Schuhmacher EMAIL: bas@wn.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Pushbutton {
+ keep -activebackground -activeforeground -background -borderwidth \
+ -cursor -disabledforeground -font -foreground -highlightbackground \
+ -highlightcolor -highlightthickness
+}
+
+# ------------------------------------------------------------------
+# PUSHBUTTON
+# ------------------------------------------------------------------
+itcl::class iwidgets::Pushbutton {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -padx padX Pad 11
+ itk_option define -pady padY Pad 4
+ itk_option define -font font Font \
+ -Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*
+ itk_option define -text text Text {}
+ itk_option define -bitmap bitmap Bitmap {}
+ itk_option define -image image Image {}
+ itk_option define -highlightthickness highlightThickness \
+ HighlightThickness 2
+ itk_option define -borderwidth borderWidth BorderWidth 2
+ itk_option define -defaultring defaultRing DefaultRing 0
+ itk_option define -defaultringpad defaultRingPad Pad 4
+ itk_option define -height height Height 0
+ itk_option define -width width Width 0
+ itk_option define -takefocus takeFocus TakeFocus 0
+
+ public method flash {}
+ public method invoke {}
+
+ protected method _relayout {{when later}}
+ protected variable _reposition "" ;# non-null => _relayout pending
+}
+
+#
+# Provide a lowercased access method for the Pushbutton class.
+#
+proc ::iwidgets::pushbutton {pathName args} {
+ uplevel ::iwidgets::Pushbutton $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Pushbutton.borderWidth 2 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Pushbutton::constructor {args} {
+ #
+ # Reconfigure the hull to act as the outer sunken ring of
+ # the pushbutton, complete with focus ring.
+ #
+ itk_option add hull.borderwidth hull.relief
+ itk_option add hull.highlightcolor
+ itk_option add hull.highlightbackground
+
+ component hull configure \
+ -borderwidth [$this cget -borderwidth]
+
+ pack propagate $itk_component(hull) no
+
+ itk_component add pushbutton {
+ button $itk_component(hull).pushbutton \
+ } {
+ usual
+ keep -underline -wraplength -state -command
+ }
+ pack $itk_component(pushbutton) -expand 1 -fill both
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+
+ #
+ # Layout the pushbutton.
+ #
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Pushbutton::destructor {} {
+ if {$_reposition != ""} {after cancel $_reposition}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -padx
+#
+# Specifies the extra space surrounding the label in the x direction.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::padx {
+ $itk_component(pushbutton) configure -padx $itk_option(-padx)
+
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -pady
+#
+# Specifies the extra space surrounding the label in the y direction.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::pady {
+ $itk_component(pushbutton) configure -pady $itk_option(-pady)
+
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -font
+#
+# Specifies the label font.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::font {
+ $itk_component(pushbutton) configure -font $itk_option(-font)
+
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -text
+#
+# Specifies the label text.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::text {
+ $itk_component(pushbutton) configure -text $itk_option(-text)
+
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -bitmap
+#
+# Specifies the label bitmap.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::bitmap {
+ $itk_component(pushbutton) configure -bitmap $itk_option(-bitmap)
+
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -image
+#
+# Specifies the label image.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::image {
+ $itk_component(pushbutton) configure -image $itk_option(-image)
+
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -highlightthickness
+#
+# Specifies the thickness of the highlight ring.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::highlightthickness {
+ $itk_component(pushbutton) configure \
+ -highlightthickness $itk_option(-highlightthickness)
+
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -borderwidth
+#
+# Specifies the width of the relief border.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::borderwidth {
+ $itk_component(pushbutton) configure -borderwidth $itk_option(-borderwidth)
+
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -defaultring
+#
+# Boolean describing whether the button displays its default ring.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::defaultring {
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -defaultringpad
+#
+# The size of the padded default ring around the button.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::defaultringpad {
+ pack $itk_component(pushbutton) \
+ -padx $itk_option(-defaultringpad) \
+ -pady $itk_option(-defaultringpad)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -height
+#
+# Specifies the height of the button inclusive of any default ring.
+# A value of zero lets the push button determine the height based
+# on the requested height plus highlightring and defaultringpad.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::height {
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# OPTION: -width
+#
+# Specifies the width of the button inclusive of any default ring.
+# A value of zero lets the push button determine the width based
+# on the requested width plus highlightring and defaultringpad.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Pushbutton::width {
+ _relayout
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: flash
+#
+# Thin wrap of standard button widget flash method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Pushbutton::flash {} {
+ $itk_component(pushbutton) flash
+}
+
+# ------------------------------------------------------------------
+# METHOD: invoke
+#
+# Thin wrap of standard button widget invoke method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Pushbutton::invoke {} {
+ $itk_component(pushbutton) invoke
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _relayout ?when?
+#
+# Adjust the width and height of the Pushbutton to accomadate all the
+# current options settings. Add back in the highlightthickness to
+# the button such that the correct reqwidth and reqheight are computed.
+# Set the width and height based on the reqwidth/reqheight,
+# highlightthickness, and ringpad. Finally, configure the defaultring
+# properly. If "when" is "now", the change is applied immediately. If
+# it is "later" or it is not specified, then the change is applied later,
+# when the application is idle.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Pushbutton::_relayout {{when later}} {
+ if {$when == "later"} {
+ if {$_reposition == ""} {
+ set _reposition [after idle [itcl::code $this _relayout now]]
+ }
+ return
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ set _reposition ""
+
+ if {$itk_option(-width) == 0} {
+ set w [expr {[winfo reqwidth $itk_component(pushbutton)] \
+ + 2 * $itk_option(-highlightthickness) \
+ + 2 * $itk_option(-borderwidth) \
+ + 2 * $itk_option(-defaultringpad)}]
+ } else {
+ set w $itk_option(-width)
+ }
+
+ if {$itk_option(-height) == 0} {
+ set h [expr {[winfo reqheight $itk_component(pushbutton)] \
+ + 2 * $itk_option(-highlightthickness) \
+ + 2 * $itk_option(-borderwidth) \
+ + 2 * $itk_option(-defaultringpad)}]
+ } else {
+ set h $itk_option(-height)
+ }
+
+ component hull configure -width $w -height $h
+
+ if {$itk_option(-defaultring)} {
+ component hull configure -relief sunken \
+ -highlightthickness [$this cget -highlightthickness] \
+ -takefocus 1
+
+ configure -takefocus 1
+
+ component pushbutton configure \
+ -highlightthickness 0 -takefocus 0
+
+ } else {
+ component hull configure -relief flat \
+ -highlightthickness 0 -takefocus 0
+
+ component pushbutton configure \
+ -highlightthickness [$this cget -highlightthickness] \
+ -takefocus 1
+
+ configure -takefocus 0
+ }
+}
diff --git a/iwidgets/generic/radiobox.itk b/iwidgets/generic/radiobox.itk
new file mode 100644
index 00000000000..282eaa71ae0
--- /dev/null
+++ b/iwidgets/generic/radiobox.itk
@@ -0,0 +1,427 @@
+#
+# Radiobox
+# ----------------------------------------------------------------------
+# Implements a radiobuttonbox. Supports adding, inserting, deleting,
+# selecting, and deselecting of radiobuttons by tag and index.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Michael J. McLennan EMAIL: mmclennan@lucent.com
+# Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Radiobox {
+ keep -background -borderwidth -cursor -disabledforeground \
+ -foreground -labelfont -selectcolor
+}
+
+# ------------------------------------------------------------------
+# RADIOBOX
+# ------------------------------------------------------------------
+itcl::class iwidgets::Radiobox {
+ inherit iwidgets::Labeledframe
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -disabledforeground \
+ disabledForeground DisabledForeground {}
+ itk_option define -selectcolor selectColor Background {}
+ itk_option define -command command Command {}
+ itk_option define -orient orient Orient vertical
+
+ public {
+ method add {tag args}
+ method buttonconfigure {index args}
+ method component {{name ""} args}
+ method delete {index}
+ method deselect {index}
+ method flash {index}
+ method get {}
+ method index {index}
+ method insert {index tag args}
+ method select {index}
+ }
+
+ protected method _command { name1 name2 opt }
+
+ private {
+ method gettag {index} ;# Get the tag of the checkbutton associated
+ ;# with a numeric index
+
+ method _rearrange {} ;# List of radiobutton tags.
+ variable _buttons {} ;# List of radiobutton tags.
+ common _modes ;# Current selection.
+ variable _unique 0 ;# Unique id for choice creation.
+ }
+}
+
+#
+# Provide a lowercased access method for the Radiobox class.
+#
+proc ::iwidgets::radiobox {pathName args} {
+ uplevel ::iwidgets::Radiobox $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Radiobox.labelMargin 10 widgetDefault
+option add *Radiobox.labelFont \
+ "-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*" widgetDefault
+option add *Radiobox.labelPos nw widgetDefault
+option add *Radiobox.borderWidth 2 widgetDefault
+option add *Radiobox.relief groove widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::constructor {args} {
+
+ #
+ # Initialize the _modes array element prior to setting the trace. This
+ # prevents the -command command (if defined) from being triggered when
+ # the first radiobutton is added via the add method.
+ #
+ set _modes($this) {}
+
+ trace variable [itcl::scope _modes($this)] w [itcl::code $this _command]
+
+ grid columnconfigure $itk_component(childsite) 0 -weight 1
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::destructor { } {
+
+ trace vdelete [itcl::scope _modes($this)] w [itcl::code $this _command]
+ catch {unset _modes($this)}
+
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -command
+#
+# Specifies a command to be evaluated upon change in the radiobox
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Radiobox::command {}
+
+# ------------------------------------------------------------------
+# OPTION: -orient
+#
+# Allows the user to orient the radiobuttons either horizontally
+# or vertically.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Radiobox::orient {
+ if {$itk_option(-orient) == "horizontal" ||
+ $itk_option(-orient) == "vertical"} {
+ _rearrange
+ } else {
+ error "Bad orientation: $itk_option(-orient). Should be\
+ \"horizontal\" or \"vertical\"."
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: index index
+#
+# Searches the radiobutton tags in the radiobox for the one with the
+# requested tag, numerical index, or keyword "end". Returns the
+# choices's numerical index if found, otherwise error.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::index {index} {
+ if {[llength $_buttons] > 0} {
+ if {[regexp {(^[0-9]+$)} $index]} {
+ if {$index < [llength $_buttons]} {
+ return $index
+ } else {
+ error "Radiobox index \"$index\" is out of range"
+ }
+
+ } elseif {$index == "end"} {
+ return [expr {[llength $_buttons] - 1}]
+
+ } else {
+ if {[set idx [lsearch $_buttons $index]] != -1} {
+ return $idx
+ }
+
+ error "bad Radiobox index \"$index\": must be number, end,\
+ or pattern"
+ }
+
+ } else {
+ error "Radiobox \"$itk_component(hull)\" has no radiobuttons"
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: add tag ?option value option value ...?
+#
+# Add a new tagged radiobutton to the radiobox at the end. The method
+# takes additional options which are passed on to the radiobutton
+# constructor. These include most of the typical radiobutton
+# options. The tag is returned.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::add {tag args} {
+ set options {-value -variable}
+ foreach option $options {
+ if {[lsearch $args $option] != -1} {
+ error "Error: specifying values for radiobutton component options\
+ \"-value\" and\n \"-variable\" is disallowed. The Radiobox must\
+ use these options when\n adding radiobuttons."
+ }
+ }
+
+ itk_component add $tag {
+ eval radiobutton $itk_component(childsite).rb[incr _unique] \
+ -variable [list [itcl::scope _modes($this)]] \
+ -anchor w \
+ -justify left \
+ -highlightthickness 0 \
+ -value $tag $args
+ } {
+ usual
+ keep -state
+ ignore -highlightthickness -highlightcolor
+ rename -font -labelfont labelFont Font
+ }
+ lappend _buttons $tag
+ grid $itk_component($tag)
+ after idle [itcl::code $this _rearrange]
+
+ return $tag
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert index tag ?option value option value ...?
+#
+# Insert the tagged radiobutton in the radiobox just before the
+# one given by index. Any additional options are passed on to the
+# radiobutton constructor. These include the typical radiobutton
+# options. The tag is returned.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::insert {index tag args} {
+ set options {-value -variable}
+ foreach option $options {
+ if {[lsearch $args $option] != -1} {
+ error "Error: specifying values for radiobutton component options\
+ \"-value\" and\n \"-variable\" is disallowed. The Radiobox must\
+ use these options when\n adding radiobuttons."
+ }
+ }
+
+ itk_component add $tag {
+ eval radiobutton $itk_component(childsite).rb[incr _unique] \
+ -variable [list [itcl::scope _modes($this)]] \
+ -highlightthickness 0 \
+ -anchor w \
+ -justify left \
+ -value $tag $args
+ } {
+ usual
+ ignore -highlightthickness -highlightcolor
+ rename -font -labelfont labelFont Font
+ }
+ set index [index $index]
+ set before [lindex $_buttons $index]
+ set _buttons [linsert $_buttons $index $tag]
+ grid $itk_component($tag)
+ after idle [itcl::code $this _rearrange]
+
+ return $tag
+}
+
+# ------------------------------------------------------------------
+# METHOD: _rearrange
+#
+# Rearrange the buttons in the childsite frame using the grid
+# geometry manager. This method was modified by Chad Smith on 3/9/00
+# to take into consideration the newly added -orient config option.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::_rearrange {} {
+ if {[set count [llength $_buttons]] > 0} {
+ if {$itk_option(-orient) == "vertical"} {
+ set row 0
+ foreach tag $_buttons {
+ grid configure $itk_component($tag) -column 0 -row $row -sticky nw
+ grid rowconfigure $itk_component(childsite) $row -weight 0
+ incr row
+ }
+ grid rowconfigure $itk_component(childsite) [expr {$count-1}] \
+ -weight 1
+ } else {
+ set col 0
+ foreach tag $_buttons {
+ grid configure $itk_component($tag) -column $col -row 0 -sticky nw
+ grid columnconfigure $itk_component(childsite) $col -weight 1
+ incr col
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: component ?name? ?arg arg arg...?
+#
+# This method overrides the base class definition to provide some
+# error checking. The user is disallowed from modifying the values
+# of the -value and -variable options for individual radiobuttons.
+# Addition of this method prompted by SF ticket 227923.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::component {{name ""} args} {
+ if {[lsearch $_buttons $name] != -1} {
+ # See if the user's trying to use the configure method. Note that
+ # because of globbing, as few characters as "co" are expanded to
+ # "config". Similarly, "configu" will expand to "configure".
+ if [regexp {^co+} [lindex $args 0]] {
+ # The user's trying to modify a radiobutton. This is all fine and
+ # dandy unless -value or -variable is being modified.
+ set options {-value -variable}
+ foreach option $options {
+ set index [lsearch $args $option]
+ if {$index != -1} {
+ # If a value is actually specified, throw an error.
+ if {[lindex $args [expr {$index + 1}]] != ""} {
+ error "Error: specifying values for radiobutton component options\
+ \"-value\" and\n \"-variable\" is disallowed. The Radiobox\
+ uses these options internally."
+ }
+ }
+ }
+ }
+ }
+
+ eval chain $name $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete index
+#
+# Delete the specified radiobutton.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::delete {index} {
+
+ set tag [gettag $index]
+ set index [index $index]
+
+ destroy $itk_component($tag)
+
+ set _buttons [lreplace $_buttons $index $index]
+
+ if {$_modes($this) == $tag} {
+ set _modes($this) {}
+ }
+ after idle [itcl::code $this _rearrange]
+ return
+}
+
+# ------------------------------------------------------------------
+# METHOD: select index
+#
+# Select the specified radiobutton.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::select {index} {
+ set tag [gettag $index]
+ $itk_component($tag) invoke
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Return the tag of the currently selected radiobutton.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::get {} {
+ return $_modes($this)
+}
+
+# ------------------------------------------------------------------
+# METHOD: deselect index
+#
+# Deselect the specified radiobutton.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::deselect {index} {
+ set tag [gettag $index]
+ $itk_component($tag) deselect
+}
+
+# ------------------------------------------------------------------
+# METHOD: flash index
+#
+# Flash the specified radiobutton.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::flash {index} {
+ set tag [gettag $index]
+ $itk_component($tag) flash
+}
+
+# ------------------------------------------------------------------
+# METHOD: buttonconfigure index ?option? ?value option value ...?
+#
+# Configure a specified radiobutton. This method allows configuration
+# of radiobuttons from the Radiobox level. The options may have any
+# of the values accepted by the add method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::buttonconfigure {index args} {
+ set tag [gettag $index]
+ eval $itk_component($tag) configure $args
+}
+
+# ------------------------------------------------------------------
+# CALLBACK METHOD: _command name1 name2 opt
+#
+# Tied to the trace on _modes($this). Whenever our -variable for our
+# radiobuttons change, this method is invoked. It in turn calls
+# the user specified tcl script given by -command.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::_command { name1 name2 opt } {
+ uplevel #0 $itk_option(-command)
+}
+
+# ------------------------------------------------------------------
+# METHOD: gettag index
+#
+# Return the tag of the checkbutton associated with a specified
+# numeric index
+# ------------------------------------------------------------------
+itcl::body iwidgets::Radiobox::gettag {index} {
+ return [lindex $_buttons [index $index]]
+}
+
diff --git a/iwidgets/generic/regexpfield.itk b/iwidgets/generic/regexpfield.itk
new file mode 100644
index 00000000000..3e899082743
--- /dev/null
+++ b/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
+}
+
diff --git a/iwidgets/generic/roman.itcl b/iwidgets/generic/roman.itcl
new file mode 100644
index 00000000000..263f574eb26
--- /dev/null
+++ b/iwidgets/generic/roman.itcl
@@ -0,0 +1,29 @@
+namespace eval ::iwidgets {
+ variable romand
+ set romand(val) {1000 900 500 400 100 90 50 40 10 9 5 4 1}
+ set romand(upper) { M CM D CD C XC L XL X IX V IV I}
+ set romand(lower) { m cm d cd c xc l xl x ix v iv i}
+
+ proc roman2 {n {case upper}} {
+ variable romand
+ set r ""
+ foreach val $romand(val) sym $romand($case) {
+ while {$n >= $val} {
+ set r "$r$sym"
+ incr n -$val
+ }
+ }
+ return $r
+ }
+
+ proc roman {n {case upper}} {
+ variable romand
+ set r ""
+ foreach val $romand(val) sym $romand($case) {
+ for {} {$n >= $val} {incr n -$val} {
+ set r "$r$sym"
+ }
+ }
+ return $r
+ }
+}
diff --git a/iwidgets/generic/scopedobject.itcl b/iwidgets/generic/scopedobject.itcl
new file mode 100644
index 00000000000..e18a0bbb4a1
--- /dev/null
+++ b/iwidgets/generic/scopedobject.itcl
@@ -0,0 +1,181 @@
+#
+# Scopedobject
+# -----------------------------------------------------------------------------
+# Implements a base class for defining Itcl classes which posses
+# scoped behavior like Tcl variables. The objects are only accessible
+# within the procedure in which they are instantiated and are deleted
+# when the procedure returns.
+#
+# Option(s):
+#
+# -enterscopecommand: Tcl command to invoke when a object enters scope
+# (i.e. when it is created ...).
+#
+# -exitscopecommand: Tcl command to invoke when a object exits scope
+# (i.e. when it is deleted ...).
+#
+# Note(s):
+#
+# Although a Scopedobject instance will automatically destroy itself
+# when it goes out of scope, one may explicity delete an instance
+# before it destroys itself.
+#
+# Example(s):
+#
+# Creating an instance at local scope in a procedure provides
+# an opportunity for tracing the entry and exiting of that
+# procedure. Users can register their proc/method tracing handlers
+# with the Scopedobject class via either of the following two ways:
+#
+# 1.) configure the "-exitscopecommand" on a Scopedobject instance;
+# e.g.
+# #!/usr/local/bin/wish
+#
+# proc tracedProc {} {
+# scopedobject #auto \
+# -exitscopecommand {puts "enter tracedProc"} \
+# -exitscopecommand {puts "exit tracedProc"}
+# }
+#
+# 2.) deriving from the Scopedobject and implementing the exit handling
+# in their derived classes destructor.
+# e.g.
+#
+# #!/usr/local/bin/wish
+#
+# class Proctrace {
+# inherit Scopedobject
+#
+# proc procname {} {
+# return [info level -1]
+# }
+#
+# constructor {args} {
+# puts "enter [procname]"
+# eval configure $args
+# }
+#
+# destructor {
+# puts "exit [procname]"
+# }
+# }
+#
+# proc tracedProc {} {
+# Proctrace #auto
+# }
+#
+# -----------------------------------------------------------------------------
+# AUTHOR: John Tucker
+# DSC Communications Corp
+# -----------------------------------------------------------------------------
+
+itcl::class iwidgets::Scopedobject {
+
+ #
+ # OPTIONS:
+ #
+ public {
+ variable enterscopecommand {}
+ variable exitscopecommand {}
+ }
+
+ #
+ # PUBLIC:
+ #
+ constructor {args} {}
+ destructor {}
+
+ #
+ # PRIVATE:
+ #
+ private {
+
+ # Implements the Tcl trace command callback which is responsible
+ # for destroying a Scopedobject instance when its corresponding
+ # Tcl variable goes out of scope.
+ #
+ method _traceCommand {varName varValue op}
+
+ # Stores the stack level of the invoking procedure in which
+ # a Scopedobject instance in created.
+ #
+ variable _level 0
+ }
+}
+
+#
+# Provide a lowercased access method for the Scopedobject class.
+#
+proc ::iwidgets::scopedobject {pathName args} {
+ uplevel ::iwidgets::Scopedobject $pathName $args
+}
+
+#--------------------------------------------------------------------------------
+# CONSTRUCTOR
+#--------------------------------------------------------------------------------
+itcl::body iwidgets::Scopedobject::constructor {args} {
+
+ # Create a local variable in the procedure which this instance was created,
+ # and then register out instance deletion command (i.e. _traceCommand)
+ # to be called whenever the local variable is unset.
+ #
+ # If this is a derived class, then we will need to perform the variable creation
+ # and tracing N levels up the stack frame, where:
+ # N = depth of inheritance hierarchy.
+ #
+ set depth [llength [$this info heritage]]
+ set _level "#[uplevel $depth info level]"
+ uplevel $_level set _localVar($this) $this
+ uplevel $_level trace variable _localVar($this) u \"[itcl::code $this _traceCommand]\"
+
+ eval configure $args
+
+ if {$enterscopecommand != {}} {
+ eval $enterscopecommand
+ }
+}
+
+#--------------------------------------------------------------------------------
+# DESTRUCTOR
+#--------------------------------------------------------------------------------
+itcl::body iwidgets::Scopedobject::destructor {} {
+
+ uplevel $_level trace vdelete _localVar($this) u \"[itcl::code $this _traceCommand]\"
+
+ if {$exitscopecommand != {}} {
+ eval $exitscopecommand
+ }
+}
+
+#--------------------------------------------------------------------------------#
+#
+# METHOD: _traceCommand
+#
+# PURPOSE:
+# Callback used to destroy instances when their locally created variable
+# goes out of scope.
+#
+itcl::body iwidgets::Scopedobject::_traceCommand {varName varValue op} {
+ delete object $this
+}
+
+#------------------------------------------------------------------------------
+#
+# OPTION: -enterscopecommand
+#
+# PURPOSE:
+# Specifies a Tcl command to invoke when a object enters scope.
+#
+itcl::configbody iwidgets::Scopedobject::enterscopecommand {
+}
+
+#------------------------------------------------------------------------------
+#
+# OPTION: -exitscopecommand
+#
+# PURPOSE:
+# Specifies a Tcl command to invoke when an object exits scope.
+#
+itcl::configbody iwidgets::Scopedobject::exitscopecommand {
+}
+
diff --git a/iwidgets/generic/scrolledcanvas.itk b/iwidgets/generic/scrolledcanvas.itk
new file mode 100644
index 00000000000..aa113548940
--- /dev/null
+++ b/iwidgets/generic/scrolledcanvas.itk
@@ -0,0 +1,477 @@
+#
+# Scrolledcanvas
+# ----------------------------------------------------------------------
+# Implements horizontal and vertical scrollbars around a canvas childsite
+# Includes options to control display of scrollbars. The standard
+# canvas options and methods are supported.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark Ulferts mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Scrolledcanvas {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -insertbackground -insertborderwidth -insertofftime -insertontime \
+ -insertwidth -jump -labelfont -selectbackground -selectborderwidth \
+ -selectforeground -textbackground -troughcolor
+}
+
+# ------------------------------------------------------------------
+# SCROLLEDCANVAS
+# ------------------------------------------------------------------
+itcl::class iwidgets::Scrolledcanvas {
+ inherit iwidgets::Scrolledwidget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -autoresize autoResize AutoResize 1
+ itk_option define -automargin autoMargin AutoMargin 0
+
+ public method childsite {}
+ public method justify {direction}
+
+ public method addtag {args}
+ public method bbox {args}
+ public method bind {args}
+ public method canvasx {args}
+ public method canvasy {args}
+ public method coords {args}
+ public method create {args}
+ public method dchars {args}
+ public method delete {args}
+ public method dtag {args}
+ public method find {args}
+ public method focus {args}
+ public method gettags {args}
+ public method icursor {args}
+ public method index {args}
+ public method insert {args}
+ public method itemconfigure {args}
+ public method itemcget {args}
+ public method lower {args}
+ public method move {args}
+ public method postscript {args}
+ public method raise {args}
+ public method scale {args}
+ public method scan {args}
+ public method select {args}
+ public method type {args}
+ public method xview {args}
+ public method yview {args}
+}
+
+#
+# Provide a lowercased access method for the Scrolledcanvas class.
+#
+proc ::iwidgets::scrolledcanvas {pathName args} {
+ uplevel ::iwidgets::Scrolledcanvas $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Scrolledcanvas.width 200 widgetDefault
+option add *Scrolledcanvas.height 230 widgetDefault
+option add *Scrolledcanvas.labelPos n widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::constructor {args} {
+ #
+ # Create a clipping frame which will provide the border for
+ # relief display.
+ #
+ itk_component add clipper {
+ frame $itk_interior.clipper
+ } {
+ usual
+
+ keep -borderwidth -relief -highlightthickness -highlightcolor
+ rename -highlightbackground -background background Background
+ }
+ grid $itk_component(clipper) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 0 -weight 1
+
+ #
+ # Create a canvas to scroll
+ #
+ itk_component add canvas {
+ canvas $itk_component(clipper).canvas \
+ -height 1.0 -width 1.0 \
+ -scrollregion "0 0 1 1" \
+ -xscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.horizsb] \
+ -yscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.vertsb]
+ } {
+ usual
+
+ ignore -highlightthickness -highlightcolor
+
+ keep -closeenough -confine -scrollregion
+ keep -xscrollincrement -yscrollincrement
+
+ rename -background -textbackground textBackground Background
+ }
+ grid $itk_component(canvas) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $itk_component(clipper) 0 -weight 1
+ grid columnconfigure $itk_component(clipper) 0 -weight 1
+
+ #
+ # Configure the command on the vertical scroll bar in the base class.
+ #
+ $itk_component(vertsb) configure \
+ -command [itcl::code $itk_component(canvas) yview]
+
+ #
+ # Configure the command on the horizontal scroll bar in the base class.
+ #
+ $itk_component(horizsb) configure \
+ -command [itcl::code $itk_component(canvas) xview]
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTURCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::destructor {} {
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -autoresize
+#
+# Automatically adjusts the scrolled region to be the bounding
+# box covering all the items in the canvas following the execution
+# of any method which creates or destroys items. Thus, as new
+# items are added, the scrollbars adjust accordingly.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledcanvas::autoresize {
+ if {$itk_option(-autoresize)} {
+ set bbox [$itk_component(canvas) bbox all]
+
+ if {$bbox != {}} {
+ set marg $itk_option(-automargin)
+ set bbox [lreplace $bbox 0 0 [expr {[lindex $bbox 0] - $marg}]]
+ set bbox [lreplace $bbox 1 1 [expr {[lindex $bbox 1] - $marg}]]
+ set bbox [lreplace $bbox 2 2 [expr {[lindex $bbox 2] + $marg}]]
+ set bbox [lreplace $bbox 3 3 [expr {[lindex $bbox 3] + $marg}]]
+ }
+
+ $itk_component(canvas) configure -scrollregion $bbox
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Returns the path name of the child site widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::childsite {} {
+ return $itk_component(canvas)
+}
+
+# ------------------------------------------------------------------
+# METHOD: justify
+#
+# Justifies the canvas scrolled region in one of four directions: top,
+# bottom, left, or right.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::justify {direction} {
+ if {[winfo ismapped $itk_component(canvas)]} {
+ update idletasks
+
+ switch $direction {
+ left {
+ $itk_component(canvas) xview moveto 0
+ }
+ right {
+ $itk_component(canvas) xview moveto 1
+ }
+ top {
+ $itk_component(canvas) yview moveto 0
+ }
+ bottom {
+ $itk_component(canvas) yview moveto 1
+ }
+ default {
+ error "bad justify argument \"$direction\": should be\
+ left, right, top, or bottom"
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# CANVAS METHODS:
+#
+# The following methods are thin wraps of standard canvas methods.
+# Consult the Tk canvas man pages for functionallity and argument
+# documentation
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: addtag tag searchSpec ?arg arg ...?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::addtag {args} {
+ return [eval $itk_component(canvas) addtag $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: bbox tagOrId ?tagOrId tagOrId ...?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::bbox {args} {
+ return [eval $itk_component(canvas) bbox $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: bind tagOrId ?sequence? ?command?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::bind {args} {
+ return [eval $itk_component(canvas) bind $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: canvasx screenx ?gridspacing?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::canvasx {args} {
+ return [eval $itk_component(canvas) canvasx $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: canvasy screeny ?gridspacing?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::canvasy {args} {
+ return [eval $itk_component(canvas) canvasy $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: coords tagOrId ?x0 y0 ...?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::coords {args} {
+ return [eval $itk_component(canvas) coords $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: create type x y ?x y ...? ?option value ...?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::create {args} {
+ set retval [eval $itk_component(canvas) create $args]
+
+ configure -autoresize $itk_option(-autoresize)
+
+ return $retval
+}
+
+# ------------------------------------------------------------------
+# METHOD: dchars tagOrId first ?last?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::dchars {args} {
+ return [eval $itk_component(canvas) dchars $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete tagOrId ?tagOrId tagOrId ...?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::delete {args} {
+ set retval [eval $itk_component(canvas) delete $args]
+
+ configure -autoresize $itk_option(-autoresize)
+
+ return $retval
+}
+
+# ------------------------------------------------------------------
+# METHOD: dtag tagOrId ?tagToDelete?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::dtag {args} {
+ eval $itk_component(canvas) dtag $args
+
+ configure -autoresize $itk_option(-autoresize)
+}
+
+# ------------------------------------------------------------------
+# METHOD: find searchCommand ?arg arg ...?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::find {args} {
+ return [eval $itk_component(canvas) find $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: focus ?tagOrId?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::focus {args} {
+ return [eval $itk_component(canvas) focus $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: gettags tagOrId
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::gettags {args} {
+ return [eval $itk_component(canvas) gettags $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: icursor tagOrId index
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::icursor {args} {
+ eval $itk_component(canvas) icursor $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: index tagOrId index
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::index {args} {
+ return [eval $itk_component(canvas) index $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert tagOrId beforeThis string
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::insert {args} {
+ eval $itk_component(canvas) insert $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: itemconfigure tagOrId ?option? ?value? ?option value ...?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::itemconfigure {args} {
+ set retval [eval $itk_component(canvas) itemconfigure $args]
+
+ configure -autoresize $itk_option(-autoresize)
+
+ return $retval
+}
+
+# ------------------------------------------------------------------
+# METHOD: itemcget tagOrId ?option?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::itemcget {args} {
+ set retval [eval $itk_component(canvas) itemcget $args]
+
+ return $retval
+}
+
+# ------------------------------------------------------------------
+# METHOD: lower tagOrId ?belowThis?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::lower {args} {
+ eval $itk_component(canvas) lower $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: move tagOrId xAmount yAmount
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::move {args} {
+ eval $itk_component(canvas) move $args
+
+ configure -autoresize $itk_option(-autoresize)
+}
+
+# ------------------------------------------------------------------
+# METHOD: postscript ?option value ...?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::postscript {args} {
+ #
+ # Make sure the fontmap is in scope.
+ #
+ set fontmap ""
+ regexp -- {-fontmap +([^ ]+)} $args all fontmap
+
+ if {$fontmap != ""} {
+ global $fontmap
+ }
+
+ return [eval $itk_component(canvas) postscript $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: raise tagOrId ?aboveThis?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::raise {args} {
+ eval $itk_component(canvas) raise $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: scale tagOrId xOrigin yOrigin xScale yScale
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::scale {args} {
+ eval $itk_component(canvas) scale $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: scan option args
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::scan {args} {
+ eval $itk_component(canvas) scan $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: select option ?tagOrId arg?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::select {args} {
+ eval $itk_component(canvas) select $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: type tagOrId
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::type {args} {
+ return [eval $itk_component(canvas) type $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: xview index
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::xview {args} {
+ eval $itk_component(canvas) xview $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: yview index
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledcanvas::yview {args} {
+ eval $itk_component(canvas) yview $args
+}
diff --git a/iwidgets/generic/scrolledframe.itk b/iwidgets/generic/scrolledframe.itk
new file mode 100644
index 00000000000..c1ab75755eb
--- /dev/null
+++ b/iwidgets/generic/scrolledframe.itk
@@ -0,0 +1,250 @@
+#
+# Scrolledframe
+# ----------------------------------------------------------------------
+# Implements horizontal and vertical scrollbars around a childsite
+# frame. Includes options to control display of scrollbars.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark Ulferts mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Scrolledframe {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -jump -labelfont -troughcolor
+}
+
+# ------------------------------------------------------------------
+# SCROLLEDFRAME
+# ------------------------------------------------------------------
+itcl::class iwidgets::Scrolledframe {
+ inherit iwidgets::Scrolledwidget
+
+ constructor {args} {}
+ destructor {}
+
+ public method childsite {}
+ public method justify {direction}
+ public method xview {args}
+ public method yview {args}
+
+ protected method _configureCanvas {}
+ protected method _configureFrame {}
+}
+
+#
+# Provide a lowercased access method for the Scrolledframe class.
+#
+proc ::iwidgets::scrolledframe {pathName args} {
+ uplevel ::iwidgets::Scrolledframe $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Scrolledframe.width 100 widgetDefault
+option add *Scrolledframe.height 100 widgetDefault
+option add *Scrolledframe.labelPos n widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledframe::constructor {args} {
+ itk_option remove iwidgets::Labeledwidget::state
+
+ #
+ # Create a clipping frame which will provide the border for
+ # relief display.
+ #
+ itk_component add clipper {
+ frame $itk_interior.clipper
+ } {
+ usual
+
+ keep -borderwidth -relief
+ }
+ grid $itk_component(clipper) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 0 -weight 1
+
+ #
+ # Create a canvas to scroll
+ #
+ itk_component add canvas {
+ canvas $itk_component(clipper).canvas \
+ -height 1.0 -width 1.0 \
+ -scrollregion "0 0 1 1" \
+ -xscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.horizsb] \
+ -yscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.vertsb] \
+ -highlightthickness 0 -takefocus 0
+ } {
+ ignore -highlightcolor -highlightthickness
+ keep -background -cursor
+ }
+ grid $itk_component(canvas) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $itk_component(clipper) 0 -weight 1
+ grid columnconfigure $itk_component(clipper) 0 -weight 1
+
+ #
+ # Configure the command on the vertical scroll bar in the base class.
+ #
+ $itk_component(vertsb) configure \
+ -command [itcl::code $itk_component(canvas) yview]
+
+ #
+ # Configure the command on the horizontal scroll bar in the base class.
+ #
+ $itk_component(horizsb) configure \
+ -command [itcl::code $itk_component(canvas) xview]
+
+ #
+ # Handle configure events on the canvas to adjust the frame size
+ # according to the scrollregion.
+ #
+ bind $itk_component(canvas) <Configure> [itcl::code $this _configureCanvas]
+
+ #
+ # Create a Frame inside canvas to hold widgets to be scrolled
+ #
+ itk_component add -protected sfchildsite {
+ frame $itk_component(canvas).sfchildsite
+ } {
+ keep -background -cursor
+ }
+ pack $itk_component(sfchildsite) -fill both -expand yes
+ $itk_component(canvas) create window 0 0 -tags frameTag \
+ -window $itk_component(sfchildsite) -anchor nw
+ set itk_interior $itk_component(sfchildsite)
+ bind $itk_component(sfchildsite) <Configure> [itcl::code $this _configureFrame]
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTURCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledframe::destructor {} {
+}
+
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Returns the path name of the child site widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledframe::childsite {} {
+ return $itk_component(sfchildsite)
+}
+
+# ------------------------------------------------------------------
+# METHOD: justify
+#
+# Justifies the scrolled region in one of four directions: top,
+# bottom, left, or right.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledframe::justify {direction} {
+ if {[winfo ismapped $itk_component(canvas)]} {
+ update idletasks
+
+ switch $direction {
+ left {
+ $itk_component(canvas) xview moveto 0
+ }
+ right {
+ $itk_component(canvas) xview moveto 1
+ }
+ top {
+ $itk_component(canvas) yview moveto 0
+ }
+ bottom {
+ $itk_component(canvas) yview moveto 1
+ }
+ default {
+ error "bad justify argument \"$direction\": should be\
+ left, right, top, or bottom"
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: xview index
+#
+# Adjust the view in the frame so that character position index
+# is displayed at the left edge of the widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledframe::xview {args} {
+ return [eval $itk_component(canvas) xview $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: yview index
+#
+# Adjust the view in the frame so that character position index
+# is displayed at the top edge of the widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledframe::yview {args} {
+ return [eval $itk_component(canvas) yview $args]
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _configureCanvas
+#
+# Responds to configure events on the canvas widget. When canvas
+# changes size, adjust frame size.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledframe::_configureCanvas {} {
+ set sr [$itk_component(canvas) cget -scrollregion]
+ set srw [lindex $sr 2]
+ set srh [lindex $sr 3]
+
+ $itk_component(sfchildsite) configure -height $srh -width $srw
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _configureFrame
+#
+# Responds to configure events on the frame widget. When the frame
+# changes size, adjust scrolling region size.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledframe::_configureFrame {} {
+ $itk_component(canvas) configure \
+ -scrollregion [$itk_component(canvas) bbox frameTag]
+}
+
diff --git a/iwidgets/generic/scrolledhtml.itk b/iwidgets/generic/scrolledhtml.itk
new file mode 100644
index 00000000000..988485f40b8
--- /dev/null
+++ b/iwidgets/generic/scrolledhtml.itk
@@ -0,0 +1,2521 @@
+# Scrolledhtml
+# ----------------------------------------------------------------------
+# Implements a scrolled html text widget by inheritance from scrolledtext
+# Import reads from an html file, while export still writes plain text
+# Also provides a render command, to display html text passed in as an
+# argument.
+#
+# This widget is HTML3.2 compliant, with the following exceptions:
+# a) nothing requiring a connection to an HTTP server is supported
+# b) some of the image alignments aren't supported, because they're not
+# supported by the text widget
+# c) the br attributes that go with the image alignments aren't implemented
+# d) background images are not supported, because they're not supported
+# by the text widget
+# e) automatic table/table cell sizing doesn't work very well.
+#
+# WISH LIST:
+# This section lists possible future enhancements.
+#
+# 1) size tables better using dlineinfo.
+# 2) make images scroll smoothly off top like they do off bottom. (limitation
+# of text widget?)
+# 3) add ability to get non-local URLs
+# a) support forms
+# b) support imagemaps
+# 4) keep track of visited links
+# 5) add tclets support
+#
+# BUGS:
+# Cells in a table can be caused to overlap. ex:
+# <table border width="100%">
+# <tr><td>cell1</td><td align=right rowspan=2>cell2</td></tr>
+# <tr><td colspan=2>cell3 w/ overlap</td>
+# </table>
+# It hasn't been fixed because 1) it's a pain to fix, 2) the fix would slow
+# tables down by a significant amount, and 3) netscape has the same
+# bug, as of V3.01, and no one seems to care.
+#
+# In order to size tables properly, they must be visible, which causes an
+# annoying jump from table to table through the document at render time.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Kris Raney EMAIL: kraney@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1996 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.
+# ======================================================================
+
+# Acknowledgements:
+#
+# Special thanks go to Sam Shen(SLShen@lbl.gov), as this code is based on his
+# tkhtml.tcl code from tk inspect. The original code is copyright 1995
+# Lawrence Berkeley Laboratory.
+#
+# This software is copyright (C) 1995 by the Lawrence Berkeley Laboratory.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that: (1) source code distributions
+# retain the above copyright notice and this paragraph in its entirety, (2)
+# distributions including binary code include the above copyright notice and
+# this paragraph in its entirety in the documentation or other materials
+# provided with the distribution, and (3) all advertising materials mentioning
+# features or use of this software display the following acknowledgement:
+# ``This product includes software developed by the University of California,
+# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+# the University nor the names of its contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+# This code is based on Angel Li's (angel@flipper.rsmas.miami.edu) HTML
+
+
+#
+# Default resources.
+#
+option add *Scrolledhtml.borderWidth 2 widgetDefault
+option add *Scrolledhtml.relief sunken widgetDefault
+option add *Scrolledhtml.scrollMargin 3 widgetDefault
+option add *Scrolledhtml.width 500 widgetDefault
+option add *Scrolledhtml.height 600 widgetDefault
+option add *Scrolledhtml.visibleItems 80x24 widgetDefault
+option add *Scrolledhtml.vscrollMode static widgetDefault
+option add *Scrolledhtml.hscrollMode static widgetDefault
+option add *Scrolledhtml.labelPos n widgetDefault
+option add *Scrolledhtml.wrap word widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Scrolledhtml {
+ keep -fontname -fontsize -fixedfont -link -alink -linkhighlight \
+ -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -insertbackground -insertborderwidth -insertofftime -insertontime \
+ -insertwidth -jump -labelfont -selectbackground -selectborderwidth \
+ -selectforeground -textbackground -textfont -troughcolor -unknownimage
+}
+
+# ------------------------------------------------------------------
+# SCROLLEDHTML
+# ------------------------------------------------------------------
+itcl::class iwidgets::Scrolledhtml {
+ inherit iwidgets::Scrolledtext
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -feedback feedBack FeedBack {}
+ itk_option define -linkcommand linkCommand LinkCommand {}
+ itk_option define -fontname fontname FontName times
+ itk_option define -fixedfont fixedFont FixedFont courier
+ itk_option define -fontsize fontSize FontSize medium
+ itk_option define -link link Link blue
+ itk_option define -alink alink ALink red
+ itk_option define -linkhighlight alink ALink red
+ itk_option define -unknownimage unknownimage File {}
+ itk_option define -textbackground textBackground Background {}
+ itk_option define -update update Update 1
+ itk_option define -debug debug Debug 0
+
+ public method import {args}
+ public method clear {}
+ public method render {html {wd .}}
+ public method title {} {return $_title}
+ public method pwd {} {return $_cwd}
+
+ protected method _setup {}
+ protected method _set_tag {}
+ protected method _reconfig_tags {}
+ protected method _append_text {text}
+ protected method _do {text}
+ protected method _definefont {name foundry family weight slant registry}
+ protected method _peek {instack}
+ protected method _push {instack value}
+ protected method _pop {instack}
+ protected method _parse_fields {array_var string}
+ protected method _href_click {cmd href}
+ protected method _set_align {align}
+ protected method _fixtablewidth {hottext table multiplier}
+
+ protected method _header {level args}
+ protected method _/header {level}
+
+ protected method _entity_a {args}
+ protected method _entity_/a {}
+ protected method _entity_address {}
+ protected method _entity_/address {}
+ protected method _entity_b {}
+ protected method _entity_/b {}
+ protected method _entity_base {{args {}}}
+ protected method _entity_basefont {{args {}}}
+ protected method _entity_big {}
+ protected method _entity_/big {}
+ protected method _entity_blockquote {}
+ protected method _entity_/blockquote {}
+ protected method _entity_body {{args {}}}
+ protected method _entity_/body {}
+ protected method _entity_br {{args {}}}
+ protected method _entity_center {}
+ protected method _entity_/center {}
+ protected method _entity_cite {}
+ protected method _entity_/cite {}
+ protected method _entity_code {}
+ protected method _entity_/code {}
+ protected method _entity_dir {{args {}}}
+ protected method _entity_/dir {}
+ protected method _entity_div {{args {}}}
+ protected method _entity_dl {{args {}}}
+ protected method _entity_/dl {}
+ protected method _entity_dt {}
+ protected method _entity_dd {}
+ protected method _entity_dfn {}
+ protected method _entity_/dfn {}
+ protected method _entity_em {}
+ protected method _entity_/em {}
+ protected method _entity_font {{args {}}}
+ protected method _entity_/font {}
+ protected method _entity_h1 {{args {}}}
+ protected method _entity_/h1 {}
+ protected method _entity_h2 {{args {}}}
+ protected method _entity_/h2 {}
+ protected method _entity_h3 {{args {}}}
+ protected method _entity_/h3 {}
+ protected method _entity_h4 {{args {}}}
+ protected method _entity_/h4 {}
+ protected method _entity_h5 {{args {}}}
+ protected method _entity_/h5 {}
+ protected method _entity_h6 {{args {}}}
+ protected method _entity_/h6 {}
+ protected method _entity_hr {{args {}}}
+ protected method _entity_i {}
+ protected method _entity_/i {}
+ protected method _entity_img {{args {}}}
+ protected method _entity_kbd {}
+ protected method _entity_/kbd {}
+ protected method _entity_li {{args {}}}
+ protected method _entity_listing {}
+ protected method _entity_/listing {}
+ protected method _entity_menu {{args {}}}
+ protected method _entity_/menu {}
+ protected method _entity_ol {{args {}}}
+ protected method _entity_/ol {}
+ protected method _entity_p {{args {}}}
+ protected method _entity_pre {{args {}}}
+ protected method _entity_/pre {}
+ protected method _entity_samp {}
+ protected method _entity_/samp {}
+ protected method _entity_small {}
+ protected method _entity_/small {}
+ protected method _entity_sub {}
+ protected method _entity_/sub {}
+ protected method _entity_sup {}
+ protected method _entity_/sup {}
+ protected method _entity_strong {}
+ protected method _entity_/strong {}
+ protected method _entity_table {{args {}}}
+ protected method _entity_/table {}
+ protected method _entity_td {{args {}}}
+ protected method _entity_/td {}
+ protected method _entity_th {{args {}}}
+ protected method _entity_/th {}
+ protected method _entity_title {}
+ protected method _entity_/title {}
+ protected method _entity_tr {{args {}}}
+ protected method _entity_/tr {}
+ protected method _entity_tt {}
+ protected method _entity_/tt {}
+ protected method _entity_u {}
+ protected method _entity_/u {}
+ protected method _entity_ul {{args {}}}
+ protected method _entity_/ul {}
+ protected method _entity_var {}
+ protected method _entity_/var {}
+
+ protected variable _title {} ;# The title of the html document
+ protected variable _licount 1 ;# list element count
+ protected variable _listyle bullet ;# list element style
+ protected variable _lipic {} ;# picture to use as bullet
+ protected variable _color black ;# current text color
+ protected variable _bgcolor #d9d9d9 ;# current background color
+ protected variable _link blue ;# current link color
+ protected variable _alink red ;# current highlight link color
+ protected variable _smallpoints "60 80 100 120 140 180 240" ;# font point
+ protected variable _mediumpoints "80 100 120 140 180 240 360" ;# sizes for
+ protected variable _largepoints "100 120 140 180 240 360 480" ;# various
+ protected variable _hugepoints "120 140 180 240 360 480 640" ;# fontsizes
+ protected variable _font times ;# name of current font
+ protected variable _rulerheight 6 ;#
+ protected variable _indentincr 4 ;# increment to indent by
+ protected variable _counter -1 ;# counter to give unique numbers
+ protected variable _left 0 ;# initial left margin
+ protected variable _left2 0 ;# subsequent left margin
+ protected variable _right 0 ;# right margin
+ protected variable _justify L ;# text justification
+ protected variable _offset 0 ;# text offset (super/subscript)
+ protected variable _textweight 0 ;# boldness of text
+ protected variable _textslant 0 ;# whether to use italics
+ protected variable _underline 0 ;# whether to use underline
+ protected variable _verbatim 0 ;# whether to skip formatting
+ protected variable _pre 0 ;# preformatted text
+ protected variable _intitle 0 ;# in <title>...</title>
+ protected variable _anchorcount 0 ;# number of anchors
+ protected variable _stack ;# array of stacks
+ protected variable _pointsndx 2 ;#
+ protected variable _fontnames ;# list of accepted font names
+ protected variable _fontinfo ;# array of font info given font name
+ protected variable _tag ;#
+ protected variable _tagl ;#
+ protected variable _tagfont ;#
+ protected variable _cwd . ;# base directory of current page
+ protected variable _anchor ;# array of indexes by anchorname
+ protected variable _defaulttextbackground;# default text background
+ protected variable _intable 0 ;# whether we are in a table now
+ protected variable _hottext ;# widget where text currently goes
+ protected variable _basefontsize 2 ;# as named
+ protected variable _unknownimg {} ;# name of unknown image
+ protected variable _images {} ;# list of images we created
+ protected variable _prevpos {} ;# temporary used for table updates
+ protected variable _prevtext {} ;# temporary used for table updates
+
+ private variable _initialized 0
+
+ private variable _defUnknownImg [::image create photo -data {
+R0lGODdhHwAgAPQAAP///wAAAMzMzC9PT76+vvnTogCR/1WRVaoAVf//qvT09OKdcWlcx19f
+X9/f339/f8vN/J2d/aq2qoKCggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ACwAAAAAHwAgAAAF/iAgjqRDnmiKmqOkqsTaToDjvudTttLjOITJbTQhGI+iQE0xMvZqQIDw
+NAEiAcqRVdKAGh0NyVCkuyqZBEmwofgRrFIxSaI0JmuA9KTrthIicWMTAQ8xWHgSe15AVgcJ
+eVMjDwECOkome22Mb0cHCzEPOiQPgwGXCjomakedA0VgY1IPDZcuP3l5YkcRDwMHqDQoEzq2
+Pz8IQkK7Bw8HDg+xO26PCAgRDcpGswEK2Dh9ItUMDdirPYUKwTKMjwDV1gHlR2oCkSmcI9UE
+BabYrGnQoolgBCGckX7yWJWDYaUMAYSRFECAwMXeiU1BHpKTB4CBR4+oBOb5By1UNgUfXj0C
+8HaP079sBCCkZIAKWst/OGPOhNBNHQmXOeftJBASRVCcEiIojQDBwIOeRo+SpGXKFFGbP6Xi
+nLWxEMsmWpEOC9XDYtigYtKSwsH2xdq2cEfRmFS1rt27eE09CAEAOw==
+}]
+}
+
+#
+# Provide a lowercased access method for the Scrolledhtml class.
+#
+proc ::iwidgets::scrolledhtml {pathName args} {
+ uplevel ::iwidgets::Scrolledhtml $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::constructor {args} {
+ # define the fonts we're going to use
+ set _fontnames ""
+ _definefont helvetica adobe helvetica "medium bold" "r o" iso8859
+ _definefont courier adobe courier "medium bold" "r o" iso8859
+ _definefont times adobe times "medium bold" "r i" iso8859
+ _definefont symbol adobe symbol "medium medium" "r r" adobe
+
+ $itk_component(text) configure -state disabled
+
+ eval itk_initialize $args
+ if {[lsearch -exact $args -linkcommand] == -1} {
+ configure -linkcommand [itcl::code $this import -link]
+ }
+ set _initialized 1
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::destructor {} {
+ foreach x $_images {
+ ::image delete $x
+ }
+ if {$_unknownimg != $_defUnknownImg} {
+ ::image delete $_unknownimg
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -fontsize
+#
+# Set the general size of the font.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledhtml::fontsize {
+ switch $itk_option(-fontsize) {
+ small { }
+ medium { }
+ large { }
+ huge { }
+ default {
+ error "bad fontsize option\
+ \"$itk_option(-fontsize)\": should\
+ be small, medium, large, or huge"
+ }
+ }
+ _reconfig_tags
+}
+
+# ------------------------------------------------------------------
+# OPTION: -fixedfont
+#
+# Set the fixed font name
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledhtml::fixedfont {
+ if {[lsearch -exact $_fontnames $itk_option(-fixedfont)] == -1} {
+ error "Invalid font name \"$itk_option(-fixedfont)\". Must be one of \
+ $_fontnames"
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -fontname
+#
+# Set the default font name
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledhtml::fontname {
+ if {[lsearch -exact $_fontnames $itk_option(-fontname)] == -1} {
+ error "Invalid font name \"$itk_option(-fontname)\". Must be one of \
+ $_fontnames"
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -textbackground
+#
+# Set the default text background
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledhtml::textbackground {
+ set _defaulttextbackground $itk_option(-textbackground)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -linkhighlight
+#
+# same as alink
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledhtml::linkhighlight {
+ configure -alink $itk_option(-linkhighlight)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -unknownimage
+#
+# set image to use as substitute for images that aren't found
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledhtml::unknownimage {
+ set oldimage $_unknownimg
+ if {$itk_option(-unknownimage) != {}} {
+ set uki $itk_option(-unknownimage)
+ if [catch { set _unknownimg [::image create photo -file $uki] } err] {
+ error "Couldn't create image $uki:\n$err\nUnknown image not found"
+ }
+ } else {
+ set _unknownimg $_defUnknownImg
+ }
+ if {$oldimage != {} && $oldimage != $_defUnknownImg} {
+ ::image delete $oldimage
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -update
+#
+# boolean indicating whether to update during rendering
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledhtml::update {
+ switch -- $itk_option(-update) {
+ 0 {}
+ 1 {}
+ true {
+ configure -update 1
+ }
+ yes {
+ configure -update 1
+ }
+ false {
+ configure -update 0
+ }
+ yes {
+ configure -update 0
+ }
+ default {
+ error "invalid -update; must be boolean"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: clear
+#
+# Clears the text out
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::clear {} {
+ $itk_component(text) config -state normal
+ $itk_component(text) delete 1.0 end
+ foreach x $_images {
+ ::image delete $x
+ }
+ set _images {}
+ _setup
+ $itk_component(text) config -state disabled
+}
+
+# ------------------------------------------------------------------
+# METHOD import ?-link? filename?#anchorname?
+#
+# read html text from a file (import filename) if the keyword link is present,
+# pathname is relative to last page, otherwise it is relative to current
+# directory. This allows the user to use a linkcommand of
+# "<widgetname> import -link"
+#
+# if '#anchorname' is appended to the filename, the page is displayed starting
+# at the anchor named 'anchorname' If an anchor is specified without a filename,
+# the current page is assumed.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::import {args} {
+
+ update idletasks
+
+ set len [llength $args]
+ if {$len != 1 && $len != 2} {
+ error "wrong # args: should be \
+ \"$itk_component(hull) import ?-link? filename\""
+ }
+ set linkname [lindex $args [expr {$len - 1}]]
+
+ #
+ # Seperate filename#anchorname
+ #
+ if ![regexp {(.*)#(.*)} $linkname dummy filename anchorname] {
+ set filename $linkname
+ }
+ if {$filename!=""} {
+ #
+ # Check for -link option
+ #
+ switch -- $len {
+ 1 {
+ #
+ # open file & set cwd to that file's directory
+ #
+ set f [open $filename r]
+ set _cwd [file dirname $filename]
+ }
+ 2 {
+ switch -- [lindex $args 0] {
+ -link {
+ #
+ # got -link, so set path relative to current locale, if path
+ # is a relative pathname
+ #
+ if {[string compare "." [file dirname $filename]] == 0} {
+ set f [open $_cwd/$filename r]
+ } else {
+ if {[string index [file dirname $filename] 0] != "/" &&\
+ [string index [file dirname $filename] 0] != "~"} {
+ set f [open $_cwd/$filename r]
+ append _cwd /
+ append _cwd [file dirname $filename]
+ } else {
+ set f [open $filename r]
+ set _cwd [file dirname $filename]
+ }
+ }
+ }
+ default {
+ # got something other than -link
+ error "invalid format: should be \
+ \"$itk_component(hull) import ?-link? filename\""
+ }
+ }
+ }
+ }
+ set txt [read $f]
+ close $f
+ render $txt $_cwd
+ }
+
+ #
+ # if an anchor was requested, move that anchor into view
+ #
+ if [ info exists anchorname] {
+ if {$anchorname!=""} {
+ if [info exists _anchor($anchorname)] {
+ $itk_component(text) see end
+ $itk_component(text) see $_anchor($anchorname)
+ }
+ } else {
+ $itk_component(text) see 0.0
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: render text ?wd?
+#
+# Clear the text, then render html formatted text. Optional wd argument
+# sets the base directory for any links or images.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::render {html {wd .}} {
+
+ update idletasks
+
+ #
+ # blank text and reset all state variables
+ #
+ clear
+ set _cwd $wd
+
+ #
+ # make text writable
+ #
+ $itk_component(text) config -state normal
+ set continuerendering 1
+ _set_tag
+ while {$continuerendering} {
+ # normal state
+ while {[set len [string length $html]]} {
+ # look for text up to the next <> element
+ if [regexp -indices "^\[^<\]+" $html match] {
+ set text [string range $html 0 [lindex $match 1]]
+ _append_text "$text"
+ set html \
+ [string range $html [expr {[lindex $match 1]+1}] end]
+ }
+ # we're either at a <>, or at the eot
+ if [regexp -indices "^<((\[^>\"\]+|(\"\[^\"\]*\"))*)>" $html match entity] {
+ regsub -all "\n" [string range $html [lindex $entity 0] \
+ [lindex $entity 1]] "" entity
+ set cmd [string tolower [lindex $entity 0]]
+ if {[info command _entity_$cmd]!=""} {
+ if {[catch {eval _entity_$cmd [lrange $entity 1 end]} bad]} {
+ if {$itk_option(-debug)} {
+ global errorInfo
+ puts stderr "render: _entity_$cmd [lrange $entity 1 end] = Error:$bad\n$errorInfo"
+ }
+ }
+ }
+ set html \
+ [string range $html [expr {[lindex $match 1]+1}] end]
+ }
+ if {$itk_option(-feedback) != {} } {
+ eval $itk_option(-feedback) $len
+ }
+ if $_verbatim break
+ }
+ # we reach here if html is empty, or _verbatim is 1
+ if !$len break
+ # _verbatim must be 1
+ # append text until next tag is reached
+ if [regexp -indices "<.*>" $html match] {
+ set text [string range $html 0 [expr {[lindex $match 0]-1}]]
+ set html [string range $html [expr {[lindex $match 0]}] end]
+ } else {
+ set text $html
+ set html ""
+ }
+ _append_text "$text"
+ }
+ $itk_component(text) config -state disabled
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _setup
+#
+# Reset all state variables to prepare for a new page.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_setup {} {
+ set _font $itk_option(-fontname)
+ set _left 0
+ set _left2 0
+ set _right 0
+ set _justify L
+ set _textweight 0
+ set _textslant 0
+ set _underline 0
+ set _verbatim 0
+ set _pre 0
+ set _title {}
+ set _intitle 0
+ set _anchorcount 0
+ set _intable 0
+ set _hottext $itk_component(text)
+ set _stack(font) {}
+ set _stack(color) {}
+ set _stack(bgcolor) {}
+ set _stack(link) {}
+ set _stack(alink) {}
+ set _stack(justify) {}
+ set _stack(listyle) {}
+ set _stack(lipic) {}
+ set _stack(href) {}
+ set _stack(pointsndx) {}
+ set _stack(left) {}
+ set _stack(left2) {}
+ set _stack(offset) {}
+ set _stack(table) {}
+ set _stack(tablewidth) {}
+ set _stack(row) {}
+ set _stack(column) {}
+ set _stack(hottext) {}
+ set _stack(tableborder) {}
+ set _stack(cellpadding) {}
+ set _stack(cellspacing) {}
+ set _stack(licount) {}
+ set _basefontsize 2
+ set _pointsndx 2
+ set _counter -1
+ set _bgcolor $_defaulttextbackground
+ set _color $itk_option(-foreground)
+ set _link $itk_option(-link)
+ set _alink $itk_option(-alink)
+ config -textbackground $_bgcolor
+ foreach x [array names _anchor] { unset _anchor($x) }
+ $itk_component(text) tag config hr -relief sunken -borderwidth 2 \
+ -font -*-*-*-*-*-*-$_rulerheight-*-*-*-*-*-*-*
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _definefont name foundry family weight slant registry
+#
+# define font information used to generate font value from font name
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_definefont \
+ {name foundry family weight slant registry} {
+ if {[lsearch -exact $_fontnames $name] == -1 } {
+ lappend _fontnames $name
+ }
+ set _fontinfo($name) \
+ [list $foundry $family $weight $slant $registry]
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _append_text text
+#
+# append text in the format described by the state variables
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_append_text {text} {
+ if {!$_intable && $itk_option(-update)} {update}
+ if {[string first "&" $text] != -1} {
+ regsub -nocase -all "&amp;" $text {\&} text
+ regsub -nocase -all "&lt;" $text "<" text
+ regsub -nocase -all "&gt;" $text ">" text
+ regsub -nocase -all "&quot;" $text "\"" text
+ }
+ if !$_verbatim {
+ if !$_pre {
+ set text [string trim $text "\n\r"]
+ regsub -all "\[ \n\r\t\]+" $text " " text
+ }
+ if ![string length $text] return
+ }
+ if {!$_pre && !$_intitle} {
+ if {[catch {$_hottext get "end - 2c"} p]} {
+ set p ""
+ }
+ set n [string index $text 0]
+ if {$n == " " && $p == " "} {
+ set text [string range $text 1 end]
+ }
+ if {[catch {$_hottext insert end $text $_tag}]} {
+ set pht [winfo parent $_hottext]
+ catch {$pht insert end $text $_tag}
+ }
+ return
+ }
+ if {$_pre && !$_intitle} {
+ if {[catch {$_hottext insert end $text $_tag}]} {
+ set pht [winfo parent $_hottext]
+ catch {$pht insert end $text $_tag}
+ }
+ return
+ }
+ append _title $text
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _set_tag
+#
+# generate a tag
+# ------------------------------------------------------------------
+# a tag is constructed as: font?B?I?U?Points-LeftLeft2RightColorJustify
+itcl::body iwidgets::Scrolledhtml::_set_tag {} {
+ set i -1
+ foreach var {foundry family weight slant registry} {
+ set $var [lindex $_fontinfo($_font) \
+ [incr i]]
+ }
+ set x_font "-$foundry-$family-"
+ set _tag $_font
+ set args {}
+ if {$_textweight > 0} {
+ append _tag "B"
+ append x_font [lindex $weight 1]-
+ } else {
+ append x_font [lindex $weight 0]-
+ }
+ if {$_textslant > 0} {
+ append _tag "I"
+ append x_font [lindex $slant 1]-
+ } else {
+ append x_font [lindex $slant 0]-
+ }
+ if {$_underline > 0} {
+ append _tag "U"
+ append args " -underline 1"
+ }
+ switch $_justify {
+ L { append args " -justify left" }
+ R { append args " -justify right" }
+ C { append args " -justify center" }
+ }
+ append args " -offset $_offset"
+
+ set pts [lindex [set [format "_%spoints" $itk_option(-fontsize)]] \
+ $_pointsndx]
+ append _tag $_pointsndx - $_left \
+ $_left2 $_right \
+ $_color $_justify
+ append x_font "normal-*-*-$pts-*-*-*-*-$registry-*"
+ if $_anchorcount {
+ set href [_peek href]
+ set href_tag href[incr _counter]
+ set tags [list $_tag $href_tag]
+ if { $itk_option(-linkcommand)!= {} } {
+ $_hottext tag bind $href_tag <1> \
+ [list uplevel #0 $itk_option(-linkcommand) $href]
+ }
+ $_hottext tag bind $href_tag <Enter> \
+ [list $_hottext tag configure $href_tag \
+ -foreground $_alink]
+ $_hottext tag bind $href_tag <Leave> \
+ [list $_hottext tag configure $href_tag \
+ -foreground $_color]
+ } else {
+ set tags $_tag
+ }
+ if {![info exists _tagl($_tag)]} {
+ set _tagfont($_tag) 1
+ eval $_hottext tag configure $_tag \
+ -foreground ${_color} \
+ -lmargin1 ${_left}m \
+ -lmargin2 ${_left2}m $args
+ if [catch {eval $_hottext tag configure $_tag \
+ -font $x_font} err] {
+ _definefont $_font * $family $weight $slant *
+ regsub \$foundry $x_font * x_font
+ regsub \$registry $x_font * x_font
+ catch {eval $_hottext tag configure $_tag -font $x_font}
+ }
+ }
+ if [info exists href_tag] {
+ $_hottext tag raise $href_tag $_tag
+ }
+ set _tag $tags
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _reconfig_tags
+#
+# reconfigure tags following a configuration change
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_reconfig_tags {} {
+ if $_initialized {
+ foreach tag [$itk_component(text) tag names] {
+ foreach efont $_fontnames {
+ if [regexp "${efont}(B?)(I?)(U?)(\[1-9\]\[0-9\]*)-" $tag t b i u points] {
+ set j -1
+ set _font $efont
+ foreach var {foundry family weight slant registry} {
+ set $var [lindex $_fontinfo($_font) [incr j]]
+ }
+ set x_font "-$foundry-$family-"
+ if {$b == "B"} {
+ append x_font [lindex $weight 1]-
+ } else {
+ append x_font [lindex $weight 0]-
+ }
+ if {$i == "I"} {
+ append x_font [lindex $slant 1]-
+ } else {
+ append x_font [lindex $slant 0]-
+ }
+ set pts [lindex [set [format \
+ "_%spoints" $itk_option(-fontsize)]] $points]
+ append x_font "normal-*-*-$pts-*-*-*-*-$registry-*"
+ $itk_component(text) tag config $tag -font $x_font
+ break
+ }
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _push instack value
+#
+# push value onto stack(instack)
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_push {instack value} {
+ set _stack($instack) [linsert $_stack($instack) 0 $value]
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _pop instack
+#
+# pop value from stack(instack)
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_pop {instack} {
+ if {$_stack($instack) == ""} {
+ error "popping empty _stack $instack"
+ }
+ set val [lindex $_stack($instack) 0]
+ set _stack($instack) [lrange $_stack($instack) 1 end]
+ return $val
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _peek instack
+#
+# peek at top value on stack(instack)
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_peek {instack} {
+ return [lindex $_stack($instack) 0]
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _parse_fields array_var string
+#
+# parse fields from a href or image tag. At the moment, doesn't support
+# spaces in field values. (e.g. alt="not avaliable")
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_parse_fields {array_var string} {
+ upvar $array_var array
+ if {$string != "{}" } {
+ regsub -all "( *)=( *)" $string = string
+ regsub -all {\\\"} $string \" string
+ while {$string != ""} {
+ if ![regexp "^ *(\[^ \n\r=\]+)=\"(\[^\"\n\r\t\]*)(.*)" $string \
+ dummy field value newstring] {
+ if ![regexp "^ *(\[^ \n\r=\]+)=(\[^\n\r\t \]*)(.*)" $string \
+ dummy field value newstring] {
+ if ![regexp "^ *(\[^ \n\r\]+)(.*)" $string dummy field newstring] {
+ error "malformed command field; field = \"$string\""
+ continue
+ }
+ set value ""
+ }
+ }
+ set array([string tolower $field]) $value
+ set string "$newstring"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _href_click
+#
+# process a click on an href
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_href_click {cmd href} {
+ uplevel #0 $cmd $href
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _set_align
+#
+# set text alignment
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_set_align {align} {
+ switch [string tolower $align] {
+ center {
+ set _justify C
+ }
+ left {
+ set _justify L
+ }
+ right {
+ set _justify R
+ }
+ default {}
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _fixtablewidth
+#
+# fix table width & height
+# essentially, with nested tables the outer table must be configured before
+# the inner table, but the idle tasks get queued up in the opposite order,
+# so process later idle tasks before sizing yourself.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_fixtablewidth {hottext table multiplier} {
+ update idletasks
+ $hottext see $_anchor($table)
+ update idletasks
+ $table configure \
+ -width [expr {$multiplier * [winfo width $hottext] - \
+ 2* [$hottext cget -padx] - \
+ 2* [$hottext cget -borderwidth]} ] \
+ -height [winfo height $table]
+ grid propagate $table 0
+}
+
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _header level
+#
+# generic entity to set state for <hn> tag
+# Accepts argument of the form ?align=[left,right,center]? ?src=<image pname>?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_header {level args} {
+ eval _parse_fields ar $args
+ _push justify $_justify
+ if [info exists ar(align)] {
+ _entity_p align=$ar(align)
+ } else {
+ _entity_p
+ }
+ if [info exists ar(src)] {
+ _entity_img src=$ar(src)
+ }
+ _push pointsndx $_pointsndx
+ set _pointsndx [expr {7-$level}]
+ incr _textweight
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _/header level
+#
+# generic entity to set state for </hn> tag
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_/header {level} {
+ set _justify [_pop justify]
+ set _pointsndx [_pop pointsndx]
+ incr _textweight -1
+ _set_tag
+ _entity_p
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_a
+#
+# add an anchor. Accepts arguments of the form ?href=filename#anchorpoint?
+# ?name=anchorname?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_a {args} {
+ _parse_fields ar $args
+ _push color $_color
+ if [info exists ar(href)] {
+ _push href $ar(href)
+ incr _anchorcount
+ set _color $_link
+ _entity_u
+ } else {
+ _push href {}
+ }
+ if [info exists ar(name)] {
+ set _anchor($ar(name)) [$itk_component(text) index end]
+ }
+ if [info exists ar(id)] {
+ set _anchor($ar(id)) [$itk_component(text) index end]
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/a
+#
+# End anchor
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/a {} {
+ set href [_pop href]
+ if {$href != {}} {
+ incr _anchorcount -1
+ set _color [_pop color]
+ _entity_/u
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_address
+#
+# display an address
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_address {} {
+ _entity_br
+ _entity_i
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/address
+#
+# change state back from address display
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/address {} {
+ _entity_/i
+ _entity_br
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_b
+#
+# Change current font to bold
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_b {} {
+ incr _textweight
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/b
+#
+# change current font back from bold
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/b {} {
+ incr _textweight -1
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_base
+#
+# set the cwd of the document
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_base {{args {}}} {
+ _parse_fields ar $args
+ if [info exists ar(href)] {
+ set _cwd [file dirname $ar(href)]
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_basefont
+#
+# set base font size
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_basefont {{args {}}} {
+ _parse_fields ar $args
+ if {[info exists ar(size)]} {
+ set _basefontsize $ar(size)
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_big
+#
+# Change current font to a bigger size
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_big {} {
+ _push pointsndx $_pointsndx
+ if {[incr _pointsndx 2] > 6} {
+ set _pointsndx 6
+ }
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/big
+#
+# change current font back from bigger size
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/big {} {
+ set _pointsndx [_pop pointsndx]
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_blockquote
+#
+# display a block quote
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_blockquote {} {
+ _entity_p
+ _push left $_left
+ incr _left $_indentincr
+ _push left2 $_left2
+ set _left2 $_left
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/blockquote
+#
+# change back from blockquote
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/blockquote {} {
+ _entity_p
+ set _left [_pop left]
+ set _left2 [_pop left2]
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_body
+#
+# begin body text. Takes argument of the form ?bgcolor=<color>? ?text=<color>?
+# ?link=<color>?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_body {{args {}}} {
+ _parse_fields ar $args
+ if [info exists ar(bgcolor)] {
+ set _bgcolor $ar(bgcolor)
+ set temp $itk_option(-textbackground)
+ config -textbackground $_bgcolor
+ set _defaulttextbackground $temp
+ }
+ if [info exists ar(text)] {
+ set _color $ar(text)
+ }
+ if [info exists ar(link)] {
+ set _link $ar(link)
+ }
+ if [info exists ar(alink)] {
+ set _alink $ar(alink)
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/body
+#
+# end body text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/body {} {
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_br
+#
+# line break
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_br {{args {}}} {
+ $_hottext insert end "\n"
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_center
+#
+# change justification to center
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_center {} {
+ _push justify $_justify
+ set _justify C
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/center
+#
+# change state back from center
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/center {} {
+ set _justify [_pop justify]
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_cite
+#
+# display citation
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_cite {} {
+ _entity_i
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/cite
+#
+# change state back from citation
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/cite {} {
+ _entity_/i
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_code
+#
+# display code listing
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_code {} {
+ _entity_pre
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/code
+#
+# end code listing
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/code {} {
+ _entity_/pre
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_dir
+#
+# display dir list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_dir {{args {}}} {
+ _entity_ul plain $args
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/dir
+#
+# end dir list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/dir {} {
+ _entity_/ul
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_div
+#
+# divide text. same as <p>
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_div {{args {}}} {
+ _entity_p $args
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_dl
+#
+# begin definition list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_dl {{args {}}} {
+ if {$_left == 0} {
+ _entity_p
+ }
+ _push left $_left
+ _push left2 $_left2
+ if {$_left2 == $_left } {
+ incr _left2 [expr {$_indentincr+3}]
+ } else {
+ incr _left2 $_indentincr
+ }
+ incr _left $_indentincr
+ _push listyle $_listyle
+ _push licount $_licount
+ set _listyle none
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/dl
+#
+# end definition list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/dl {} {
+ set _left [_pop left]
+ set _left2 [_pop left2]
+ set _listyle [_pop listyle]
+ set _licount [_pop licount]
+ _set_tag
+ if {$_left == 0} {
+ _entity_p
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_dt
+#
+# definition term
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_dt {} {
+ set _left [expr {$_left2 - 3}]
+ _set_tag
+ _entity_p
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_dd
+#
+# definition definition
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_dd {} {
+ set _left $_left2
+ _set_tag
+ _entity_br
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_dfn
+#
+# display defining instance of a term
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_dfn {} {
+ _entity_i
+ _entity_b
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/dfn
+#
+# change state back from defining instance of term
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/dfn {} {
+ _entity_/b
+ _entity_/i
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_em
+#
+# display emphasized text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_em {} {
+ _entity_i
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/em
+#
+# change state back from emphasized text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/em {} {
+ _entity_/i
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_font
+#
+# set font size and color
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_font {{args {}}} {
+ _parse_fields ar $args
+ _push pointsndx $_pointsndx
+ _push color $_color
+ if [info exists ar(size)] {
+ if {![regexp {^[+-].*} $ar(size)]} {
+ set _pointsndx $ar(size)
+ } else {
+ set _pointsndx [expr {$_basefontsize $ar(size)}]
+ }
+ if { $_pointsndx > 6 } {
+ set _pointsndx 6
+ } else {
+ if { $_pointsndx < 0 } {
+ set _pointsndx 0
+ }
+ }
+ }
+ if {[info exists ar(color)]} {
+ set _color $ar(color)
+ }
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/font
+#
+# close current font size
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/font {} {
+ set _pointsndx [_pop pointsndx]
+ set _color [_pop color]
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_h1
+#
+# display header level 1.
+# Accepts argument of the form ?align=[left,right,center]? ?src=<image pname>?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_h1 {{args {}}} {
+ _header 1 $args
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/h1
+#
+# change state back from header 1
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/h1 {} {
+ _/header 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_h2
+#
+# display header level 2
+# Accepts argument of the form ?align=[left,right,center]? ?src=<image pname>?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_h2 {{args {}}} {
+ _header 2 $args
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/h2
+#
+# change state back from header 2
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/h2 {} {
+ _/header 2
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_h3
+#
+# display header level 3
+# Accepts argument of the form ?align=[left,right,center]? ?src=<image pname>?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_h3 {{args {}}} {
+ _header 3 $args
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/h3
+#
+# change state back from header 3
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/h3 {} {
+ _/header 3
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_h4
+#
+# display header level 4
+# Accepts argument of the form ?align=[left,right,center]? ?src=<image pname>?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_h4 {{args {}}} {
+ _header 4 $args
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/h4
+#
+# change state back from header 4
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/h4 {} {
+ _/header 4
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_h5
+#
+# display header level 5
+# Accepts argument of the form ?align=[left,right,center]? ?src=<image pname>?
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_h5 {{args {}}} {
+ _header 5 $args
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/h5
+#
+# change state back from header 5
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/h5 {} {
+ _/header 5
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_h6
+#
+# display header level 6
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_h6 {{args {}}} {
+ _header 6 $args
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/h6
+#
+# change state back from header 6
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/h6 {} {
+ _/header 6
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_hr
+#
+# Add a horizontal rule
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_hr {{args {}}} {
+ _parse_fields ar $args
+ if [info exists ar(size)] {
+ set font "-font -*-*-*-*-*-*-$ar(size)-*-*-*-*-*-*-*"
+ } else {
+ set font "-font -*-*-*-*-*-*-2-*-*-*-*-*-*-*"
+ }
+ if [info exists ar(width)] {
+ }
+ if [info exists ar(noshade)] {
+ set relief "-relief flat"
+ set background "-background black"
+ } else {
+ set relief "-relief sunken"
+ set background ""
+ }
+# if [info exists ar(align)] {
+# $_hottext tag config hr$_counter -justify $ar(align)
+# set justify -justify $ar(align)
+# } else {
+# set justify ""
+# }
+ eval $_hottext tag config hr[incr _counter] $relief $background $font \
+ -borderwidth 2
+ _entity_p
+ $_hottext insert end " \n" hr$_counter
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_i
+#
+# display italicized text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_i {} {
+ incr _textslant
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/i
+#
+# change state back from italicized text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/i {} {
+ incr _textslant -1
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_img
+#
+# display an image. takes argument of the form img=<filename>
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_img {{args {}}} {
+ _parse_fields ar $args
+ set alttext "<image>"
+
+ #
+ # If proper argument exists
+ #
+ if [info exists ar(src)] {
+ set imgframe $_hottext.img[incr _counter]
+ #
+ # if this is an anchor
+ #
+ if $_anchorcount {
+ # create link colored border
+ frame $imgframe -borderwidth 2 -background $_link
+ bind $imgframe <Enter> \
+ [list $imgframe configure -background $_alink]
+ bind $imgframe <Leave> \
+ [list $imgframe configure -background $_link]
+ } else {
+ # create plain frame
+ frame $imgframe -borderwidth 0 -background $_color
+ }
+
+ #
+ # try to load image
+ #
+ if {[string index $ar(src) 0] == "/" || [string index $ar(src) 0] == "~"} {
+ set file $ar(src)
+ } else {
+ set file $_cwd/$ar(src)
+ }
+ if [catch {set img [::image create photo -file $file]} err] {
+ if {[info exists ar(width)] && [info exists ar(height)] } {
+ # suggestions exist, so make frame appropriate size and add a border
+ $imgframe configure -width $ar(width) -height $ar(height) -borderwidth 2
+ pack propagate $imgframe false
+ }
+
+ #
+ # If alt text is specified, display that
+ #
+ if [info exists ar(alt)] {
+ # add a border
+ $imgframe configure -borderwidth 2
+ set win $imgframe.text
+ label $win -text "$ar(alt)" -background $_bgcolor \
+ -foreground $_color
+ } else {
+ #
+ # use 'unknown image'
+ set win $imgframe.image#auto
+ #
+ # make label containing image
+ #
+ label $win -image $_unknownimg -borderwidth 0 -background $_bgcolor
+ }
+ pack $win -fill both -expand true
+
+ } else { ;# no error loading image
+ lappend _images $img
+ set win $imgframe.$img
+
+ #
+ # make label containing image
+ #
+ label $win -image $img -borderwidth 0
+ }
+ pack $win
+
+ #
+ # set alignment
+ #
+ set align bottom
+ if [info exists ar(align)] {
+ switch $ar(align) {
+ middle {
+ set align center
+ }
+ right {
+ set align center
+ }
+ default {
+ set align [string tolower $ar(align)]
+ }
+ }
+ }
+
+ #
+ # create window in text to display image
+ #
+ $_hottext window create end -window \
+ $imgframe -align $align
+
+ #
+ # set tag for window
+ #
+ $_hottext tag add $_tag $imgframe
+ if $_anchorcount {
+ set href [_peek href]
+ set href_tag href[incr _counter]
+ set tags [list $_tag $href_tag]
+ if { $itk_option(-linkcommand)!= {} } {
+ bind $win <1> [list uplevel #0 $itk_option(-linkcommand) $href]
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_kbd
+#
+# Display keyboard input
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_kbd {} {
+ incr _textweight
+ _entity_tt
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/kbd
+#
+# change state back from displaying keyboard input
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/kbd {} {
+ _entity_/tt
+ incr _textweight -1
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_li
+#
+# begin new list entry
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_li {{args {}}} {
+ _parse_fields ar $args
+ if [info exists ar(value)] {
+ set _licount $ar(value)
+ }
+ _entity_br
+ switch -exact $_listyle {
+ bullet {
+ set old_font $_font
+ set _font symbol
+ _set_tag
+ $_hottext insert end "\xb7" $_tag
+ set _font $old_font
+ _set_tag
+ }
+ none {
+ }
+ picture {
+ _entity_img src="$_lipic" width=4 height=4 align=middle
+ }
+ A {
+ _entity_b
+ $_hottext insert end [format "%c) " [expr {$_licount + 0x40}]] $_tag
+ _entity_/b
+ incr _licount
+ }
+ a {
+ _entity_b
+ $_hottext insert end [format "%c) " [expr {$_licount + 0x60}]] $_tag
+ _entity_/b
+ incr _licount
+ }
+ I {
+ _entity_b
+ $_hottext insert end "[::iwidgets::roman $_licount]) " $_tag
+ _entity_/b
+ incr _licount
+ }
+ i {
+ _entity_b
+ $_hottext insert end "[::iwidgets::roman $_licount lower])] " $_tag
+ _entity_/b
+ incr _licount
+ }
+ default {
+ _entity_b
+ $_hottext insert end "$_licount) " $_tag
+ _entity_/b
+ incr _licount
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_listing
+#
+# diplay code listing
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_listing {} {
+ _entity_pre
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/listing
+#
+# end code listing
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/listing {} {
+ _entity_/pre
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_menu
+#
+# diplay menu list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_menu {{args {}}} {
+ _entity_ul plain $args
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/menu
+#
+# end menu list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/menu {} {
+ _entity_/ul
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_ol
+#
+# begin ordered list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_ol {{args {}}} {
+ _parse_fields ar $args
+ if $_left {
+ _entity_br
+ } else {
+ _entity_p
+ }
+ if {![info exists ar(type)]} {
+ set ar(type) 1
+ }
+ _push licount $_licount
+ if [info exists ar(start)] {
+ set _licount $ar(start)
+ } else {
+ set _licount 1
+ }
+ _push left $_left
+ _push left2 $_left2
+ if {$_left2 == $_left } {
+ incr _left2 [expr {$_indentincr+3}]
+ } else {
+ incr _left2 $_indentincr
+ }
+ incr _left $_indentincr
+ _push listyle $_listyle
+ set _listyle $ar(type)
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/ol
+#
+# end ordered list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/ol {} {
+ set _left [_pop left]
+ set _left2 [_pop left2]
+ set _listyle [_pop listyle]
+ set _licount [_pop licount]
+ _set_tag
+ _entity_p
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_p
+#
+# paragraph break
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_p {{args {}}} {
+ _parse_fields ar $args
+ if [info exists ar(align)] {
+ _set_align $ar(align)
+ } else {
+ set _justify L
+ }
+ _set_tag
+ if [info exists ar(id)] {
+ set _anchor($ar(id)) [$itk_component(text) index end]
+ }
+ set x [$_hottext get end-3c]
+ set y [$_hottext get end-2c]
+ if {$x == "" && $y == ""} return
+ if {$y == ""} {
+ $_hottext insert end "\n\n"
+ return
+ }
+ if {$x == "\n" && $y == "\n"} return
+ if {$y == "\n"} {
+ $_hottext insert end "\n"
+ return
+ }
+ $_hottext insert end "\n\n"
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_pre
+#
+# display preformatted text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_pre {{args {}}} {
+ _entity_tt
+ _entity_br
+ incr _pre
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/pre
+#
+# change state back from preformatted text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/pre {} {
+ _entity_/tt
+ set _pre 0
+ _entity_p
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_samp
+#
+# display sample text.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_samp {} {
+ _entity_kbd
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/samp
+#
+# switch back to non-sample text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/samp {} {
+ _entity_/kbd
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_small
+#
+# Change current font to a smaller size
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_small {} {
+ _push pointsndx $_pointsndx
+ if {[incr _pointsndx -2] < 0} {
+ set _pointsndx 0
+ }
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/small
+#
+# change current font back from smaller size
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/small {} {
+ set _pointsndx [_pop pointsndx]
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_sub
+#
+# display subscript
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_sub {} {
+ _push offset $_offset
+ incr _offset -2
+ _entity_small
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/sub
+#
+# switch back to non-subscript
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/sub {} {
+ set _offset [_pop offset]
+ _entity_/small
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_sup
+#
+# display superscript
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_sup {} {
+ _push offset $_offset
+ incr _offset 4
+ _entity_small
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/sup
+#
+# switch back to non-superscript
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/sup {} {
+ set _offset [_pop offset]
+ _entity_/small
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_strong
+#
+# display strong text. (i.e. make font bold)
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_strong {} {
+ incr _textweight
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/strong
+#
+# switch back to non-strong text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/strong {} {
+ incr _textweight -1
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_table
+#
+# display a table.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_table {{args {}}} {
+ _parse_fields ar $args
+ _entity_p
+ set _intable 1
+
+ _push row -1
+ _push column 0
+ _push hottext $_hottext
+ _push justify $_justify
+ _push justify L
+ # push color information for master of table, then push info for table
+ _push color $_color
+ _push bgcolor $_bgcolor
+ _push link $_link
+ _push alink $_alink
+ if [info exists ar(bgcolor)] {
+ set _bgcolor $ar(bgcolor)
+ }
+ if [info exists ar(text)] {
+ set _color $ar(text)
+ }
+ if [info exists ar(link)] {
+ set _link $ar(link)
+ }
+ if [info exists ar(alink)] {
+ set _alink $ar(alink)
+ }
+ _push color $_color
+ _push bgcolor $_bgcolor
+ _push link $_link
+ _push alink $_alink
+ # push fake first row to avoid using optional /tr tag
+ # (This needs to set a real color - not the empty string
+ # becaule later code will try to use those values.)
+ _push color $_color
+ _push bgcolor $_bgcolor
+ _push link {}
+ _push alink {}
+
+ if {[info exists ar(align)]} {
+ _set_align $ar(align)
+ _set_tag
+ _append_text " "
+ }
+ set _justify L
+
+ if [info exists ar(id)] {
+ set _anchor($ar(id)) [$itk_component(text) index end]
+ }
+ if [info exists ar(cellpadding)] {
+ _push cellpadding $ar(cellpadding)
+ } else {
+ _push cellpadding 0
+ }
+ if [info exists ar(cellspacing)] {
+ _push cellspacing $ar(cellspacing)
+ } else {
+ _push cellspacing 0
+ }
+ if {[info exists ar(border)]} {
+ _push tableborder 1
+ set relief raised
+ if {$ar(border)==""} {
+ set ar(border) 2
+ }
+ } else {
+ _push tableborder 0
+ set relief flat
+ set ar(border) 2
+ }
+ _push table [set table $_hottext.table[incr _counter]]
+ iwidgets::labeledwidget $table -foreground $_color -background $_bgcolor -labelpos n
+ if {[info exists ar(title)]} {
+ $table configure -labeltext $ar(title)
+ }
+ #
+ # create window in text to display table
+ #
+ $_hottext window create end -window $table
+
+ set table [$table childsite]
+ set _anchor($table) [$_hottext index "end - 1 line"]
+ $table configure -borderwidth $ar(border) -relief $relief
+
+ if {[info exists ar(width)]} {
+ _push tablewidth $ar(width)
+ } else {
+ _push tablewidth 0
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/table
+#
+# end table
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/table {} {
+ if {$_intable} {
+ _pop tableborder
+ set table [[_pop table] childsite]
+ _pop row
+ _pop column
+ _pop cellspacing
+ _pop cellpadding
+ # pop last row's defaults
+ _pop color
+ _pop bgcolor
+ _pop link
+ _pop alink
+ # pop table defaults
+ _pop color
+ _pop bgcolor
+ _pop link
+ _pop alink
+ # restore table master defaults
+ set _color [_pop color]
+ set _bgcolor [_pop bgcolor]
+ set _link [_pop link]
+ set _alink [_pop alink]
+ foreach x [grid slaves $table] {
+ set text [$x get 1.0 end]
+ set tl [split $text \n]
+ set max 0
+ foreach l $tl {
+ set len [string length $l]
+ if {$len > $max} {
+ set max $len
+ }
+ }
+ if {$max > [$x cget -width]} {
+ $x configure -width $max
+ }
+ if {[$x cget -height] == 1} {
+ $x configure -height [lindex [split [$x index "end - 1 chars"] "."] 0]
+ }
+ }
+ $_hottext configure -state disabled
+ set _hottext [_pop hottext]
+ $_hottext configure -state normal
+ if {[set tablewidth [_pop tablewidth]]!="0"} {
+ if {[string index $tablewidth \
+ [expr {[string length $tablewidth] -1}]] == "%"} {
+ set multiplier [expr {[string trimright $tablewidth "%"] / 100.0}]
+ set idletask [after idle [itcl::code "$this _fixtablewidth $_hottext $table $multiplier"]]
+ } else {
+ $table configure -width $tablewidth
+ grid propagate $table 0
+ }
+ }
+ _pop justify
+ set _justify [_pop justify]
+ _entity_br
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_td
+#
+# start table data cell
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_td {{args {}}} {
+ if $_intable {
+ _parse_fields ar $args
+ set table [[_peek table] childsite]
+ if {![info exists ar(colspan)]} {
+ set ar(colspan) 1
+ }
+ if {![info exists ar(rowspan)]} {
+ set ar(rowspan) 1
+ }
+ if {![info exists ar(width)]} {
+ set ar(width) 10
+ }
+ if {![info exists ar(height)]} {
+ set ar(height) 0
+ }
+ if [info exists ar(bgcolor)] {
+ set _bgcolor $ar(bgcolor)
+ } else {
+ set _bgcolor [_peek bgcolor]
+ }
+ if [info exists ar(text)] {
+ set _color $ar(text)
+ } else {
+ set _color [_peek color]
+ }
+ if [info exists ar(link)] {
+ set _link $ar(link)
+ } else {
+ set _link [_peek link]
+ }
+ if [info exists ar(alink)] {
+ set _alink $ar(alink)
+ } else {
+ set _alink [_peek alink]
+ }
+ $_hottext configure -state disabled
+ set cellpadding [_peek cellpadding]
+ set cellspacing [_peek cellspacing]
+ set _hottext $table.cell[incr _counter]
+ text $_hottext -relief flat -width $ar(width) -height $ar(height) \
+ -highlightthickness 0 -wrap word -cursor $itk_option(-cursor) \
+ -wrap word -cursor $itk_option(-cursor) \
+ -padx $cellpadding -pady $cellpadding
+ if {$_color != ""} {
+ $_hottext config -foreground $_color
+ }
+ if {$_bgcolor != ""} {
+ $_hottext config -background $_bgcolor
+ }
+ if [info exists ar(nowrap)] {
+ $_hottext configure -wrap none
+ }
+ if [_peek tableborder] {
+ $_hottext configure -relief sunken
+ }
+ set row [_peek row]
+ if {$row < 0} {
+ set row 0
+ }
+ set column [_pop column]
+ if {$column < 0} {
+ set column 0
+ }
+ while {[grid slaves $table -row $row -column $column] != ""} {
+ incr column
+ }
+ grid $_hottext -sticky nsew -row $row -column $column \
+ -columnspan $ar(colspan) -rowspan $ar(rowspan) \
+ -padx $cellspacing -pady $cellspacing
+ grid columnconfigure $table $column -weight 1
+ _push column [expr {$column + $ar(colspan)}]
+ if [info exists ar(align)] {
+ _set_align $ar(align)
+ } else {
+ set _justify [_peek justify]
+ }
+ _set_tag
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/td
+#
+# end table data cell
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/td {} {
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_th
+#
+# start table header
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_th {{args {}}} {
+ if $_intable {
+ _parse_fields ar $args
+ if [info exists ar(align)] {
+ _entity_td $args
+ } else {
+ _entity_td align=center $args
+ }
+ _entity_b
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/th
+#
+# end table data cell
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/th {} {
+ _entity_/td
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_title
+#
+# begin title of document
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_title {} {
+ set _intitle 1
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/title
+#
+# end title
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/title {} {
+ set _intitle 0
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_tr
+#
+# start table row
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_tr {{args {}}} {
+ if $_intable {
+ _parse_fields ar $args
+ _pop justify
+ if [info exists ar(align)] {
+ _set_align $ar(align)
+ _push justify $_justify
+ } else {
+ _push justify L
+ }
+ # pop last row's colors
+ _pop color
+ _pop bgcolor
+ _pop link
+ _pop alink
+ if [info exists ar(bgcolor)] {
+ set _bgcolor $ar(bgcolor)
+ } else {
+ set _bgcolor [_peek bgcolor]
+ }
+ if [info exists ar(text)] {
+ set _color $ar(text)
+ } else {
+ set _color [_peek color]
+ }
+ if [info exists ar(link)] {
+ set _link $ar(link)
+ } else {
+ set _link [_peek link]
+ }
+ if [info exists ar(alink)] {
+ set _alink $ar(alink)
+ } else {
+ set _alink [_peek alink]
+ }
+ # push this row's defaults
+ _push color $_color
+ _push bgcolor $_bgcolor
+ _push link $_link
+ _push alink $_alink
+ $_hottext configure -state disabled
+ _push row [expr {[_pop row] + 1}]
+ _pop column
+ _push column 0
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/tr
+#
+# end table row
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/tr {} {
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_tt
+#
+# Show typewriter text, using the font given by -fixedfont
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_tt {} {
+ _push font $_font
+ set _font $itk_option(-fixedfont)
+ set _verbatim 1
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/tt
+#
+# Change back to non-typewriter mode to display text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/tt {} {
+ set _font [_pop font]
+ set _verbatim 0
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_u
+#
+# display underlined text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_u {} {
+ incr _underline
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/u
+#
+# change back from underlined text
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/u {} {
+ incr _underline -1
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_ul
+#
+# begin unordered list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_ul {{args {}}} {
+ _parse_fields ar $args
+ if $_left {
+ _entity_br
+ } else {
+ _entity_p
+ }
+ if [info exists ar(id)] {
+ set _anchor($ar(id)) [$itk_component(text) index end]
+ }
+ _push left $_left
+ _push left2 $_left2
+ if {$_left2 == $_left } {
+ incr _left2 [expr {$_indentincr+3}]
+ } else {
+ incr _left2 $_indentincr
+ }
+ incr _left $_indentincr
+ _push listyle $_listyle
+ _push licount $_licount
+ if [info exists ar(plain)] {
+ set _listyle none
+ } {
+ set _listyle bullet
+ }
+ if [info exists ar(dingbat)] {
+ set ar(src) $ar(dingbat)
+ }
+ _push lipic $_lipic
+ if [info exists ar(src)] {
+ set _listyle picture
+ set _lipic $ar(src)
+ }
+ _set_tag
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/ul
+#
+# end unordered list
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/ul {} {
+ set _left [_pop left]
+ set _left2 [_pop left2]
+ set _listyle [_pop listyle]
+ set _licount [_pop licount]
+ set _lipic [_pop lipic]
+ _set_tag
+ _entity_p
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_var
+#
+# Display variable
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_var {} {
+ _entity_i
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _entity_/var
+#
+# change state back from variable display
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledhtml::_entity_/var {} {
+ _entity_/i
+}
diff --git a/iwidgets/generic/scrolledlistbox.itk b/iwidgets/generic/scrolledlistbox.itk
new file mode 100644
index 00000000000..18d6a61a08f
--- /dev/null
+++ b/iwidgets/generic/scrolledlistbox.itk
@@ -0,0 +1,732 @@
+#
+# Scrolledlistbox
+# ----------------------------------------------------------------------
+# Implements a scrolled listbox with additional options to manage
+# horizontal and vertical scrollbars. This includes options to control
+# which scrollbars are displayed and the method, i.e. statically,
+# dynamically, or none at all.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Scrolledlistbox {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -jump -labelfont -selectbackground -selectborderwidth \
+ -selectforeground -textbackground -textfont -troughcolor
+}
+
+# ------------------------------------------------------------------
+# SCROLLEDLISTBOX
+# ------------------------------------------------------------------
+itcl::class iwidgets::Scrolledlistbox {
+ inherit iwidgets::Scrolledwidget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -dblclickcommand dblClickCommand Command {}
+ itk_option define -selectioncommand selectionCommand Command {}
+ itk_option define -width width Width 0
+ itk_option define -height height Height 0
+ itk_option define -visibleitems visibleItems VisibleItems 20x10
+ itk_option define -state state State normal
+
+ public method curselection {}
+ public method activate {index}
+ public method bbox {index}
+ public method clear {}
+ public method see {index}
+ public method index {index}
+ public method delete {first {last {}}}
+ public method get {first {last {}}}
+ public method getcurselection {}
+ public method insert {index args}
+ public method nearest {y}
+ public method scan {option args}
+ public method selection {option first {last {}}}
+ public method size {}
+ public method selecteditemcount {}
+ public method justify {direction}
+ public method sort {{mode ascending}}
+ public method xview {args}
+ public method yview {args}
+ public method itemconfigure {args}
+
+ protected method _makeSelection {}
+ protected method _dblclick {}
+ protected method _fixIndex {index}
+
+ #
+ # List the event sequences that invoke single and double selection.
+ # Should these change in the underlying Tk listbox, then they must
+ # change here too.
+ #
+ common doubleSelectSeq { \
+ <Double-1>
+ }
+
+ common singleSelectSeq { \
+ <Control-Key-backslash> \
+ <Control-Key-slash> \
+ <Key-Escape> \
+ <Shift-Key-Select> \
+ <Control-Shift-Key-space> \
+ <Key-Select> \
+ <Key-space> \
+ <Control-Shift-Key-End> \
+ <Control-Key-End> \
+ <Control-Shift-Key-Home> \
+ <Control-Key-Home> \
+ <Key-Down> \
+ <Key-Up> \
+ <Shift-Key-Down> \
+ <Shift-Key-Up> \
+ <Control-Button-1> \
+ <Shift-Button-1> \
+ <ButtonRelease-1> \
+ }
+}
+
+#
+# Provide a lowercased access method for the Scrolledlistbox class.
+#
+proc ::iwidgets::scrolledlistbox {pathName args} {
+ uplevel ::iwidgets::Scrolledlistbox $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Scrolledlistbox.labelPos n widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::constructor {args} {
+ #
+ # Our -width and -height options are slightly different than
+ # those implemented by our base class, so we're going to
+ # remove them and redefine our own.
+ #
+ itk_option remove iwidgets::Scrolledwidget::width
+ itk_option remove iwidgets::Scrolledwidget::height
+
+ #
+ # Create the listbox.
+ #
+ itk_component add listbox {
+ listbox $itk_interior.listbox \
+ -width 1 -height 1 \
+ -xscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.horizsb] \
+ -yscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.vertsb]
+ } {
+ usual
+
+ keep -borderwidth -exportselection -relief -selectmode
+ keep -listvariable
+
+ rename -font -textfont textFont Font
+ rename -background -textbackground textBackground Background
+ rename -highlightbackground -background background Background
+ }
+ grid $itk_component(listbox) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 0 -weight 1
+
+ #
+ # Configure the command on the vertical scroll bar in the base class.
+ #
+ $itk_component(vertsb) configure \
+ -command [itcl::code $itk_component(listbox) yview]
+
+ #
+ # Configure the command on the horizontal scroll bar in the base class.
+ #
+ $itk_component(horizsb) configure \
+ -command [itcl::code $itk_component(listbox) xview]
+
+ #
+ # Create a set of bindings for monitoring the selection and install
+ # them on the listbox component.
+ #
+ foreach seq $singleSelectSeq {
+ bind SLBSelect$this $seq [itcl::code $this _makeSelection]
+ }
+
+ foreach seq $doubleSelectSeq {
+ bind SLBSelect$this $seq [itcl::code $this _dblclick]
+ }
+
+ bindtags $itk_component(listbox) \
+ [linsert [bindtags $itk_component(listbox)] end SLBSelect$this]
+
+ #
+ # Also create a set of bindings for disabling the scrolledlistbox.
+ # Since the command for it is "break", we can drop the $this since
+ # they don't need to be unique to the object level.
+ #
+ if {[bind SLBDisabled] == {}} {
+ foreach seq $singleSelectSeq {
+ bind SLBDisabled $seq break
+ }
+
+ bind SLBDisabled <Button-1> break
+
+ foreach seq $doubleSelectSeq {
+ bind SLBDisabled $seq break
+ }
+ }
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTURCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::destructor {} {
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -dblclickcommand
+#
+# Specify a command to be executed upon double click of a listbox
+# item. Also, create a couple of bindings used for specific
+# selection modes
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledlistbox::dblclickcommand {}
+
+# ------------------------------------------------------------------
+# OPTION: -selectioncommand
+#
+# Specifies a command to be executed upon selection of a listbox
+# item. The command will be called upon each selection regardless
+# of selection mode..
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledlistbox::selectioncommand {}
+
+# ------------------------------------------------------------------
+# OPTION: -width
+#
+# Specifies the width of the scrolled list box as an entire unit.
+# The value may be specified in any of the forms acceptable to
+# Tk_GetPixels. Any additional space needed to display the other
+# components such as margins and scrollbars force the listbox
+# to be compressed. A value of zero along with the same value for
+# the height causes the value given for the visibleitems option
+# to be applied which administers geometry constraints in a different
+# manner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledlistbox::width {
+ if {$itk_option(-width) != 0} {
+ set shell [lindex [grid info $itk_component(listbox)] 1]
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $shell]} {
+ grid propagate $shell no
+ }
+
+ $itk_component(listbox) configure -width 1
+ $shell configure \
+ -width [winfo pixels $shell $itk_option(-width)]
+ } else {
+ configure -visibleitems $itk_option(-visibleitems)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -height
+#
+# Specifies the height of the scrolled list box as an entire unit.
+# The value may be specified in any of the forms acceptable to
+# Tk_GetPixels. Any additional space needed to display the other
+# components such as margins and scrollbars force the listbox
+# to be compressed. A value of zero along with the same value for
+# the width causes the value given for the visibleitems option
+# to be applied which administers geometry constraints in a different
+# manner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledlistbox::height {
+ if {$itk_option(-height) != 0} {
+ set shell [lindex [grid info $itk_component(listbox)] 1]
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $shell]} {
+ grid propagate $shell no
+ }
+
+ $itk_component(listbox) configure -height 1
+ $shell configure \
+ -height [winfo pixels $shell $itk_option(-height)]
+ } else {
+ configure -visibleitems $itk_option(-visibleitems)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -visibleitems
+#
+# Specified the widthxheight in characters and lines for the listbox.
+# This option is only administered if the width and height options
+# are both set to zero, otherwise they take precedence. With the
+# visibleitems option engaged, geometry constraints are maintained
+# only on the listbox. The size of the other components such as
+# labels, margins, and scrollbars, are additive and independent,
+# effecting the overall size of the scrolled list box. In contrast,
+# should the width and height options have non zero values, they
+# are applied to the scrolled list box as a whole. The listbox
+# is compressed or expanded to maintain the geometry constraints.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledlistbox::visibleitems {
+ if {[regexp {^[0-9]+x[0-9]+$} $itk_option(-visibleitems)]} {
+ if {($itk_option(-width) == 0) && \
+ ($itk_option(-height) == 0)} {
+ set chars [lindex [split $itk_option(-visibleitems) x] 0]
+ set lines [lindex [split $itk_option(-visibleitems) x] 1]
+
+ set shell [lindex [grid info $itk_component(listbox)] 1]
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {! [grid propagate $shell]} {
+ grid propagate $shell yes
+ }
+
+ $itk_component(listbox) configure -width $chars -height $lines
+ }
+
+ } else {
+ error "bad visibleitems option\
+ \"$itk_option(-visibleitems)\": should be\
+ widthxheight"
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -state
+#
+# Specifies the state of the scrolledlistbox which may be either
+# disabled or normal. In a disabled state, the scrolledlistbox
+# does not accept user selection. The default is normal.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledlistbox::state {
+ set tags [bindtags $itk_component(listbox)]
+
+ #
+ # If the state is normal, then we need to remove the disabled
+ # bindings if they exist. If the state is disabled, then we need
+ # to install the disabled bindings if they haven't been already.
+ #
+ switch -- $itk_option(-state) {
+ normal {
+ $itk_component(listbox) configure \
+ -foreground $itk_option(-foreground)
+ $itk_component(listbox) configure \
+ -selectforeground $itk_option(-selectforeground)
+ if {[set index [lsearch $tags SLBDisabled]] != -1} {
+ bindtags $itk_component(listbox) \
+ [lreplace $tags $index $index]
+ }
+ }
+
+ disabled {
+ $itk_component(listbox) configure \
+ -foreground $itk_option(-disabledforeground)
+ $itk_component(listbox) configure \
+ -selectforeground $itk_option(-disabledforeground)
+ if {[set index [lsearch $tags SLBDisabled]] == -1} {
+ bindtags $itk_component(listbox) \
+ [linsert $tags 1 SLBDisabled]
+ }
+ }
+ default {
+ error "bad state value \"$itk_option(-state)\":\
+ must be normal or disabled"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: curselection
+#
+# Returns a list containing the indices of all the elements in the
+# listbox that are currently selected.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::curselection {} {
+ return [$itk_component(listbox) curselection]
+}
+
+# ------------------------------------------------------------------
+# METHOD: activate index
+#
+# Sets the active element to the one indicated by index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::activate {index} {
+ return [$itk_component(listbox) activate [_fixIndex $index]]
+}
+
+# ------------------------------------------------------------------
+# METHOD: bbox index
+#
+# Returns four element list describing the bounding box for the list
+# item at index
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::bbox {index} {
+ return [$itk_component(listbox) bbox [_fixIndex $index]]
+}
+
+# ------------------------------------------------------------------
+# METHOD clear
+#
+# Clear the listbox area of all items.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::clear {} {
+ delete 0 end
+}
+
+# ------------------------------------------------------------------
+# METHOD: see index
+#
+# Adjusts the view such that the element given by index is visible.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::see {index} {
+ $itk_component(listbox) see [_fixIndex $index]
+}
+
+# ------------------------------------------------------------------
+# METHOD: index index
+#
+# Returns the decimal string giving the integer index corresponding
+# to index. The index value may be a integer number, active,
+# anchor, end, @x,y, or a pattern.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::index {index} {
+ if {[regexp {(^[0-9]+$)|(^active$)|(^anchor$)|(^end$)|(^@-?[0-9]+,-?[0-9]+$)} $index]} {
+ return [$itk_component(listbox) index $index]
+
+ } else {
+ set indexValue [lsearch -glob [get 0 end] $index]
+ if {$indexValue == -1} {
+ error "bad Scrolledlistbox index \"$index\": must be active,\
+ anchor, end, @x,y, number, or a pattern"
+ }
+ return $indexValue
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: _fixIndex index
+#
+# Similar to the regular "index" method, but it only converts
+# the index to a numerical value if it is a string pattern. If
+# the index is in the proper form to be used with the listbox,
+# it is left alone. This fixes problems associated with converting
+# an index such as "end" to a numerical value.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::_fixIndex {index} {
+ if {[regexp {(^[0-9]+$)|(^active$)|(^anchor$)|(^end$)|(^@[0-9]+,[0-9]+$)} \
+ $index]} {
+ return $index
+
+ } else {
+ set indexValue [lsearch -glob [get 0 end] $index]
+
+ if {$indexValue == -1} {
+ error "bad Scrolledlistbox index \"$index\": must be active,\
+ anchor, end, @x,y, number, or a pattern"
+ }
+ return $indexValue
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete first ?last?
+#
+# Delete one or more elements from list box based on the first and
+# last index values. Indexes may be a number, active, anchor, end,
+# @x,y, or a pattern.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::delete {first {last {}}} {
+ set first [_fixIndex $first]
+
+ if {$last != {}} {
+ set last [_fixIndex $last]
+ } else {
+ set last $first
+ }
+
+ eval $itk_component(listbox) delete $first $last
+}
+
+# ------------------------------------------------------------------
+# METHOD: get first ?last?
+#
+# Returns the elements of the listbox indicated by the indexes.
+# Indexes may be a number, active, anchor, end, @x,y, ora pattern.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::get {first {last {}}} {
+ set first [_fixIndex $first]
+
+ if {$last != {}} {
+ set last [_fixIndex $last]
+ }
+
+ if {$last == {}} {
+ return [$itk_component(listbox) get $first]
+ } else {
+ return [$itk_component(listbox) get $first $last]
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: getcurselection
+#
+# Returns the contents of the listbox element indicated by the current
+# selection indexes. Short cut version of get and curselection
+# command combination.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::getcurselection {} {
+ set rlist {}
+
+ if {[selecteditemcount] > 0} {
+ set cursels [$itk_component(listbox) curselection]
+
+ switch $itk_option(-selectmode) {
+ single -
+ browse {
+ set rlist [$itk_component(listbox) get $cursels]
+ }
+
+ multiple -
+ extended {
+ foreach sel $cursels {
+ lappend rlist [$itk_component(listbox) get $sel]
+ }
+ }
+ }
+ }
+
+ return $rlist
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert index string ?string ...?
+#
+# Insert zero or more elements in the list just before the element
+# given by index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::insert {index args} {
+ set index [_fixIndex $index]
+
+ eval $itk_component(listbox) insert $index $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: nearest y
+#
+# Given a y-coordinate within the listbox, this command returns the
+# index of the visible listbox element nearest to that y-coordinate.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::nearest {y} {
+ $itk_component(listbox) nearest $y
+}
+
+# ------------------------------------------------------------------
+# METHOD: scan option args
+#
+# Implements scanning on listboxes.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::scan {option args} {
+ eval $itk_component(listbox) scan $option $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: selection option first ?last?
+#
+# Adjusts the selection within the listbox. The index value may be
+# a integer number, active, anchor, end, @x,y, or a pattern.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::selection {option first {last {}}} {
+ set first [_fixIndex $first]
+
+ if {$last != {}} {
+ set last [_fixIndex $last]
+ $itk_component(listbox) selection $option $first $last
+ } else {
+ $itk_component(listbox) selection $option $first
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: size
+#
+# Returns a decimal string indicating the total number of elements
+# in the listbox.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::size {} {
+ return [$itk_component(listbox) size]
+}
+
+# ------------------------------------------------------------------
+# METHOD: selecteditemcount
+#
+# Returns a decimal string indicating the total number of selected
+# elements in the listbox.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::selecteditemcount {} {
+ return [llength [$itk_component(listbox) curselection]]
+}
+
+# ------------------------------------------------------------------
+# METHOD: justify direction
+#
+# Justifies the list scrolled region in one of four directions: top,
+# bottom, left, or right.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::justify {direction} {
+ switch $direction {
+ left {
+ $itk_component(listbox) xview moveto 0
+ }
+ right {
+ $itk_component(listbox) xview moveto 1
+ }
+ top {
+ $itk_component(listbox) yview moveto 0
+ }
+ bottom {
+ $itk_component(listbox) yview moveto 1
+ }
+ default {
+ error "bad justify argument \"$direction\": should\
+ be left, right, top, or bottom"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: sort mode
+#
+# Sort the current list. This can take any sort switch from
+# the lsort command: ascii, integer, real, command,
+# increasing/ascending, decreasing/descending, etc.
+#
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::sort {{mode ascending}} {
+
+ set vals [$itk_component(listbox) get 0 end]
+ if {[llength $vals] == 0} {return}
+
+ switch $mode {
+ ascending {set mode increasing}
+ descending {set mode decreasing}
+ }
+
+ $itk_component(listbox) delete 0 end
+ if {[catch {eval $itk_component(listbox) insert end \
+ [lsort -${mode} $vals]} errorstring]} {
+ error "bad sort argument \"$mode\": must be a valid argument to the\
+ Tcl lsort command"
+ }
+
+ return
+}
+
+# ------------------------------------------------------------------
+# METHOD: xview args
+#
+# Change or query the vertical position of the text in the list box.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::xview {args} {
+ return [eval $itk_component(listbox) xview $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: yview args
+#
+# Change or query the horizontal position of the text in the list box.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::yview {args} {
+ return [eval $itk_component(listbox) yview $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: itemconfigure args
+#
+# This is a wrapper method around the new tk8.3 itemconfigure command
+# for the listbox.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::itemconfigure {args} {
+ return [eval $itk_component(listbox) itemconfigure $args]
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _makeSelection
+#
+# Evaluate the selection command.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::_makeSelection {} {
+ uplevel #0 $itk_option(-selectioncommand)
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _dblclick
+#
+# Evaluate the double click command option if not empty.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledlistbox::_dblclick {} {
+ uplevel #0 $itk_option(-dblclickcommand)
+}
+
diff --git a/iwidgets/generic/scrolledtext.itk b/iwidgets/generic/scrolledtext.itk
new file mode 100644
index 00000000000..67f40ea339f
--- /dev/null
+++ b/iwidgets/generic/scrolledtext.itk
@@ -0,0 +1,501 @@
+#
+# Scrolledtext
+# ----------------------------------------------------------------------
+# Implements a scrolled text widget with additional options to manage
+# the vertical scrollbar. This includes options to control the method
+# in which the scrollbar is displayed, i.e. statically or dynamically.
+# Options also exist for adding a label to the scrolled text area and
+# controlling its position. Import/export of methods are provided for
+# file I/O.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Scrolledtext {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -insertbackground -insertborderwidth -insertofftime -insertontime \
+ -insertwidth -jump -labelfont -selectbackground -selectborderwidth \
+ -selectforeground -textbackground -textfont -troughcolor
+}
+
+# ------------------------------------------------------------------
+# SCROLLEDTEXT
+# ------------------------------------------------------------------
+itcl::class iwidgets::Scrolledtext {
+ inherit iwidgets::Scrolledwidget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -width width Width 0
+ itk_option define -height height Height 0
+ itk_option define -visibleitems visibleItems VisibleItems 80x24
+
+ public method bbox {index}
+ public method childsite {}
+ public method clear {}
+ public method import {filename {index end}}
+ public method export {filename}
+ public method compare {index1 op index2}
+ public method debug {args}
+ public method delete {first {last {}}}
+ public method dlineinfo {index}
+ public method get {index1 {index2 {}}}
+ public method image {option args}
+ public method index {index}
+ public method insert {args}
+ public method mark {option args}
+ public method scan {option args}
+ public method search {args}
+ public method see {index}
+ public method tag {option args}
+ public method window {option args}
+ public method xview {args}
+ public method yview {args}
+}
+
+#
+# Provide a lowercased access method for the Scrolledtext class.
+#
+proc ::iwidgets::scrolledtext {pathName args} {
+ uplevel ::iwidgets::Scrolledtext $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Scrolledtext.labelPos n widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::constructor {args} {
+ #
+ # Our -width and -height options are slightly different than
+ # those implemented by our base class, so we're going to
+ # remove them and redefine our own.
+ #
+ itk_option remove iwidgets::Scrolledwidget::width
+ itk_option remove iwidgets::Scrolledwidget::height
+
+ #
+ # Create a clipping frame which will provide the border for
+ # relief display.
+ #
+ itk_component add clipper {
+ frame $itk_interior.clipper
+ } {
+ usual
+
+ keep -borderwidth -relief -highlightthickness -highlightcolor
+ rename -highlightbackground -background background Background
+ }
+ grid $itk_component(clipper) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $_interior 0 -weight 1
+ grid columnconfigure $_interior 0 -weight 1
+
+ #
+ # Create the text area.
+ #
+ itk_component add text {
+ text $itk_component(clipper).text \
+ -width 1 -height 1 \
+ -xscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.horizsb] \
+ -yscrollcommand \
+ [itcl::code $this _scrollWidget $itk_interior.vertsb] \
+ -borderwidth 0 -highlightthickness 0
+ } {
+ usual
+
+ ignore -highlightthickness -highlightcolor -borderwidth
+
+ keep -exportselection -padx -pady -setgrid \
+ -spacing1 -spacing2 -spacing3 -state -tabs -wrap
+
+ rename -font -textfont textFont Font
+ rename -background -textbackground textBackground Background
+ }
+ grid $itk_component(text) -row 0 -column 0 -sticky nsew
+ grid rowconfigure $itk_component(clipper) 0 -weight 1
+ grid columnconfigure $itk_component(clipper) 0 -weight 1
+
+ #
+ # Configure the command on the vertical scroll bar in the base class.
+ #
+ $itk_component(vertsb) configure \
+ -command [itcl::code $itk_component(text) yview]
+
+ #
+ # Configure the command on the horizontal scroll bar in the base class.
+ #
+ $itk_component(horizsb) configure \
+ -command [itcl::code $itk_component(text) xview]
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTURCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::destructor {} {
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -width
+#
+# Specifies the width of the scrolled text as an entire unit.
+# The value may be specified in any of the forms acceptable to
+# Tk_GetPixels. Any additional space needed to display the other
+# components such as labels, margins, and scrollbars force the text
+# to be compressed. A value of zero along with the same value for
+# the height causes the value given for the visibleitems option
+# to be applied which administers geometry constraints in a different
+# manner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledtext::width {
+ if {$itk_option(-width) != 0} {
+ set shell [lindex [grid info $itk_component(clipper)] 1]
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $shell]} {
+ grid propagate $shell no
+ }
+
+ $itk_component(text) configure -width 1
+ $shell configure \
+ -width [winfo pixels $shell $itk_option(-width)]
+ } else {
+ configure -visibleitems $itk_option(-visibleitems)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -height
+#
+# Specifies the height of the scrolled text as an entire unit.
+# The value may be specified in any of the forms acceptable to
+# Tk_GetPixels. Any additional space needed to display the other
+# components such as labels, margins, and scrollbars force the text
+# to be compressed. A value of zero along with the same value for
+# the width causes the value given for the visibleitems option
+# to be applied which administers geometry constraints in a different
+# manner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledtext::height {
+ if {$itk_option(-height) != 0} {
+ set shell [lindex [grid info $itk_component(clipper)] 1]
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $shell]} {
+ grid propagate $shell no
+ }
+
+ $itk_component(text) configure -height 1
+ $shell configure \
+ -height [winfo pixels $shell $itk_option(-height)]
+ } else {
+ configure -visibleitems $itk_option(-visibleitems)
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -visibleitems
+#
+# Specified the widthxheight in characters and lines for the text.
+# This option is only administered if the width and height options
+# are both set to zero, otherwise they take precedence. With the
+# visibleitems option engaged, geometry constraints are maintained
+# only on the text. The size of the other components such as
+# labels, margins, and scroll bars, are additive and independent,
+# effecting the overall size of the scrolled text. In contrast,
+# should the width and height options have non zero values, they
+# are applied to the scrolled text as a whole. The text is
+# compressed or expanded to maintain the geometry constraints.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledtext::visibleitems {
+ if {[regexp {^[0-9]+x[0-9]+$} $itk_option(-visibleitems)]} {
+ if {($itk_option(-width) == 0) && \
+ ($itk_option(-height) == 0)} {
+ set chars [lindex [split $itk_option(-visibleitems) x] 0]
+ set lines [lindex [split $itk_option(-visibleitems) x] 1]
+
+ set shell [lindex [grid info $itk_component(clipper)] 1]
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {! [grid propagate $shell]} {
+ grid propagate $shell yes
+ }
+
+ $itk_component(text) configure -width $chars -height $lines
+ }
+
+ } else {
+ error "bad visibleitems option\
+ \"$itk_option(-visibleitems)\": should be\
+ widthxheight"
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Returns the path name of the child site widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::childsite {} {
+ return $itk_component(text)
+}
+
+# ------------------------------------------------------------------
+# METHOD: bbox index
+#
+# Returns four element list describing the bounding box for the list
+# item at index
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::bbox {index} {
+ return [$itk_component(text) bbox $index]
+}
+
+# ------------------------------------------------------------------
+# METHOD clear
+#
+# Clear the text area.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::clear {} {
+ $itk_component(text) delete 1.0 end
+}
+
+# ------------------------------------------------------------------
+# METHOD import filename
+#
+# Load text from an existing file (import filename)
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::import {filename {index end}} {
+ set f [open $filename r]
+ insert $index [read $f]
+ close $f
+}
+
+# ------------------------------------------------------------------
+# METHOD export filename
+#
+# write text to a file (export filename)
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::export {filename} {
+ set f [open $filename w]
+
+ set txt [$itk_component(text) get 1.0 end]
+ puts $f $txt
+
+ flush $f
+ close $f
+}
+
+# ------------------------------------------------------------------
+# METHOD compare index1 op index2
+#
+# Compare indices according to relational operator.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::compare {index1 op index2} {
+ return [$itk_component(text) compare $index1 $op $index2]
+}
+
+# ------------------------------------------------------------------
+# METHOD debug ?boolean?
+#
+# Activates consistency checks in B-tree code associated with text
+# widgets.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::debug {args} {
+ eval $itk_component(text) debug $args
+}
+
+# ------------------------------------------------------------------
+# METHOD delete first ?last?
+#
+# Delete a range of characters from the text.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::delete {first {last {}}} {
+ $itk_component(text) delete $first $last
+}
+
+# ------------------------------------------------------------------
+# METHOD dlineinfo index
+#
+# Returns a five element list describing the area occupied by the
+# display line containing index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::dlineinfo {index} {
+ return [$itk_component(text) dlineinfo $index]
+}
+
+# ------------------------------------------------------------------
+# METHOD get index1 ?index2?
+#
+# Return text from start index to end index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::get {index1 {index2 {}}} {
+ return [$itk_component(text) get $index1 $index2]
+}
+
+# ------------------------------------------------------------------
+# METHOD image option ?arg arg ...?
+#
+# Manipulate images dependent on options.
+#
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::image {option args} {
+ return [eval $itk_component(text) image $option $args]
+}
+
+
+# ------------------------------------------------------------------
+# METHOD index index
+#
+# Return position corresponding to index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::index {index} {
+ return [$itk_component(text) index $index]
+}
+
+# ------------------------------------------------------------------
+# METHOD insert index chars ?tagList?
+#
+# Insert text at index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::insert {args} {
+ eval $itk_component(text) insert $args
+}
+
+# ------------------------------------------------------------------
+# METHOD mark option ?arg arg ...?
+#
+# Manipulate marks dependent on options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::mark {option args} {
+ return [eval $itk_component(text) mark $option $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD scan option args
+#
+# Implements scanning on texts.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::scan {option args} {
+ eval $itk_component(text) scan $option $args
+}
+
+# ------------------------------------------------------------------
+# METHOD search ?switches? pattern index ?varName?
+#
+# Searches the text for characters matching a pattern.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::search {args} {
+ #-----------------------------------------------------------
+ # BUG FIX: csmith (Chad Smith: csmith@adc.com), 11/18/99
+ #-----------------------------------------------------------
+ # Need to run this command up one level on the stack since
+ # the text widget may modify one of the arguments, which is
+ # the case when -count is specified.
+ #-----------------------------------------------------------
+ return [uplevel eval $itk_component(text) search $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD see index
+#
+# Adjusts the view in the window so the character at index is
+# visible.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::see {index} {
+ $itk_component(text) see $index
+}
+
+# ------------------------------------------------------------------
+# METHOD tag option ?arg arg ...?
+#
+# Manipulate tags dependent on options.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::tag {option args} {
+ return [eval $itk_component(text) tag $option $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD window option ?arg arg ...?
+#
+# Manipulate embedded windows.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::window {option args} {
+ return [eval $itk_component(text) window $option $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD xview
+#
+# Changes x view in widget's window.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::xview {args} {
+ return [eval $itk_component(text) xview $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD yview
+#
+# Changes y view in widget's window.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledtext::yview {args} {
+ return [eval $itk_component(text) yview $args]
+}
+
diff --git a/iwidgets/generic/scrolledwidget.itk b/iwidgets/generic/scrolledwidget.itk
new file mode 100644
index 00000000000..58094dd79fa
--- /dev/null
+++ b/iwidgets/generic/scrolledwidget.itk
@@ -0,0 +1,376 @@
+#
+# Scrolledwidget
+# ----------------------------------------------------------------------
+# Implements a general purpose base class for scrolled widgets, by
+# creating the necessary horizontal and vertical scrollbars and
+# providing protected methods for controlling their display. The
+# derived class needs to take advantage of the fact that the grid
+# is used and the vertical scrollbar is in row 0, column 2 and the
+# horizontal scrollbar in row 2, column 0.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark Ulferts mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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 Scrolledwidget {
+ keep -background -borderwidth -cursor -highlightcolor -highlightthickness
+ keep -activebackground -activerelief -jump -troughcolor
+ keep -labelfont -foreground
+}
+
+# ------------------------------------------------------------------
+# SCROLLEDWIDGET
+# ------------------------------------------------------------------
+itcl::class iwidgets::Scrolledwidget {
+ inherit iwidgets::Labeledwidget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -sbwidth sbWidth Width 15
+ itk_option define -scrollmargin scrollMargin ScrollMargin 3
+ itk_option define -vscrollmode vscrollMode VScrollMode static
+ itk_option define -hscrollmode hscrollMode HScrollMode static
+ itk_option define -width width Width 30
+ itk_option define -height height Height 30
+
+ protected method _scrollWidget {wid first last}
+ protected method _vertScrollbarDisplay {mode}
+ protected method _horizScrollbarDisplay {mode}
+ protected method _configureEvent {}
+
+ protected variable _vmode off ;# Vertical scroll mode
+ protected variable _hmode off ;# Vertical scroll mode
+ protected variable _recheckHoriz 1 ;# Flag to check need for
+ ;# horizontal scrollbar
+ protected variable _recheckVert 1 ;# Flag to check need for
+ ;# vertical scrollbar
+
+ protected variable _interior {}
+}
+
+#
+# Provide a lowercased access method for the Scrolledwidget class.
+#
+proc ::iwidgets::scrolledwidget {pathName args} {
+ uplevel ::iwidgets::Scrolledwidget $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Scrolledwidget.labelPos n widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledwidget::constructor {args} {
+
+ #
+ # Turn off the borderwidth on the hull and save off the
+ # interior for later use.
+ #
+ component hull configure -borderwidth 0
+ set _interior $itk_interior
+
+ #
+ # Check if the scrollbars need mapping upon a configure event.
+ #
+ bind $_interior <Configure> [itcl::code $this _configureEvent]
+
+ #
+ # Turn off propagation in the containing shell.
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $_interior]} {
+ grid propagate $_interior no
+ }
+
+ #
+ # Create the vertical scroll bar
+ #
+ itk_component add vertsb {
+ scrollbar $itk_interior.vertsb -orient vertical
+ } {
+ usual
+ keep -borderwidth -elementborderwidth -jump -relief
+ rename -highlightbackground -background background Background
+ }
+
+ #
+ # Create the horizontal scrollbar
+ #
+ itk_component add horizsb {
+ scrollbar $itk_interior.horizsb -orient horizontal
+ } {
+ usual
+ keep -borderwidth -elementborderwidth -jump -relief
+ rename -highlightbackground -background background Background
+ }
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# DESTURCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledwidget::destructor {} {
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -sbwidth
+#
+# Set the width of the scrollbars.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledwidget::sbwidth {
+ $itk_component(vertsb) configure -width $itk_option(-sbwidth)
+ $itk_component(horizsb) configure -width $itk_option(-sbwidth)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -scrollmargin
+#
+# Set the distance between the scrollbars and the list box.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledwidget::scrollmargin {
+ set pixels [winfo pixels $_interior $itk_option(-scrollmargin)]
+
+ if {$_hmode == "on"} {
+ grid rowconfigure $_interior 1 -minsize $pixels
+ }
+
+ if {$_vmode == "on"} {
+ grid columnconfigure $_interior 1 -minsize $pixels
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -vscrollmode
+#
+# Enable/disable display and mode of veritcal scrollbars.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledwidget::vscrollmode {
+ switch $itk_option(-vscrollmode) {
+ static {
+ _vertScrollbarDisplay on
+ }
+
+ dynamic -
+ none {
+ _vertScrollbarDisplay off
+ }
+
+ default {
+ error "bad vscrollmode option\
+ \"$itk_option(-vscrollmode)\": should be\
+ static, dynamic, or none"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -hscrollmode
+#
+# Enable/disable display and mode of horizontal scrollbars.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledwidget::hscrollmode {
+ switch $itk_option(-hscrollmode) {
+ static {
+ _horizScrollbarDisplay on
+ }
+
+ dynamic -
+ none {
+ _horizScrollbarDisplay off
+ }
+
+ default {
+ error "bad hscrollmode option\
+ \"$itk_option(-hscrollmode)\": should be\
+ static, dynamic, or none"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -width
+#
+# Specifies the width of the scrolled widget. The value may be
+# specified in any of the forms acceptable to Tk_GetPixels.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledwidget::width {
+ $_interior configure -width \
+ [winfo pixels $_interior $itk_option(-width)]
+}
+
+# ------------------------------------------------------------------
+# OPTION: -height
+#
+# Specifies the height of the scrolled widget. The value may be
+# specified in any of the forms acceptable to Tk_GetPixels.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Scrolledwidget::height {
+ $_interior configure -height \
+ [winfo pixels $_interior $itk_option(-height)]
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _vertScrollbarDisplay mode
+#
+# Displays the vertical scrollbar based on the input mode.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledwidget::_vertScrollbarDisplay {mode} {
+ switch $mode {
+ on {
+ set _vmode on
+
+ grid columnconfigure $_interior 1 -minsize \
+ [winfo pixels $_interior $itk_option(-scrollmargin)]
+ grid $itk_component(vertsb) -row 0 -column 2 -sticky ns
+ }
+
+ off {
+ set _vmode off
+
+ grid columnconfigure $_interior 1 -minsize 0
+ grid forget $itk_component(vertsb)
+ }
+
+ default {
+ error "invalid argument \"$mode\": should be on or off"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _horizScrollbarDisplay mode
+#
+# Displays the horizontal scrollbar based on the input mode.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledwidget::_horizScrollbarDisplay {mode} {
+ switch $mode {
+ on {
+ set _hmode on
+
+ grid rowconfigure $_interior 1 -minsize \
+ [winfo pixels $_interior $itk_option(-scrollmargin)]
+ grid $itk_component(horizsb) -row 2 -column 0 -sticky ew
+ }
+
+ off {
+ set _hmode off
+
+ grid rowconfigure $_interior 1 -minsize 0
+ grid forget $itk_component(horizsb)
+ }
+
+ default {
+ error "invalid argument \"$mode\": should be on or off"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _scrollWidget wid first last
+#
+# Performs scrolling and display of scrollbars based on the total
+# and maximum frame size as well as the current -vscrollmode and
+# -hscrollmode settings. Parameters are automatic scroll parameters.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledwidget::_scrollWidget {wid first last} {
+ $wid set $first $last
+
+ if {$wid == $itk_component(vertsb)} {
+ if {$itk_option(-vscrollmode) == "dynamic"} {
+ if {($_recheckVert != 1) && ($_vmode == "on")} {
+ return
+ } else {
+ set _recheckVert 0
+ }
+
+ if {($first == 0) && ($last == 1)} {
+ if {$_vmode != "off"} {
+ _vertScrollbarDisplay off
+ }
+
+ } else {
+ if {$_vmode != "on"} {
+ _vertScrollbarDisplay on
+ }
+ }
+ }
+
+ } elseif {$wid == $itk_component(horizsb)} {
+ if {$itk_option(-hscrollmode) == "dynamic"} {
+ if {($_recheckHoriz != 1) && ($_hmode == "on")} {
+ return
+ } else {
+ set _recheckHoriz 0
+ }
+
+ if {($first == 0) && ($last == 1)} {
+ if {$_hmode != "off"} {
+ _horizScrollbarDisplay off
+ }
+
+ } else {
+ if {$_hmode != "on"} {
+ _horizScrollbarDisplay on
+ }
+ }
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _configureEvent
+#
+# Resets the recheck flags which determine if we'll try and map
+# the scrollbars in dynamic mode.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Scrolledwidget::_configureEvent {} {
+ update idletasks
+ set _recheckVert 1
+ set _recheckHoriz 1
+}
diff --git a/iwidgets/generic/selectionbox.itk b/iwidgets/generic/selectionbox.itk
new file mode 100644
index 00000000000..9957f261bc1
--- /dev/null
+++ b/iwidgets/generic/selectionbox.itk
@@ -0,0 +1,560 @@
+#
+# Selectionbox
+# ----------------------------------------------------------------------
+# Implements a selection box composed of a scrolled list of items and
+# a selection entry field. The user may choose any of the items displayed
+# in the scrolled list of alternatives and the selection field will be
+# filled with the choice. The user is also free to enter a new value in
+# the selection entry field. Both the list and entry areas have labels.
+# A child site is also provided in which the user may create other widgets
+# to be used in conjunction with the selection box.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Selectionbox {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -insertbackground -insertborderwidth -insertofftime -insertontime \
+ -insertwidth -jump -labelfont -selectbackground -selectborderwidth \
+ -selectforeground -textbackground -textfont -troughcolor
+}
+
+# ------------------------------------------------------------------
+# SELECTIONBOX
+# ------------------------------------------------------------------
+itcl::class iwidgets::Selectionbox {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -childsitepos childSitePos Position center
+ itk_option define -margin margin Margin 7
+ itk_option define -itemson itemsOn ItemsOn true
+ itk_option define -selectionon selectionOn SelectionOn true
+ itk_option define -width width Width 260
+ itk_option define -height height Height 320
+
+ public method childsite {}
+ public method get {}
+ public method curselection {}
+ public method clear {component}
+ public method insert {component index args}
+ public method delete {first {last {}}}
+ public method size {}
+ public method scan {option args}
+ public method nearest {y}
+ public method index {index}
+ public method selection {option args}
+ public method selectitem {}
+
+ private method _packComponents {{when later}}
+
+ private variable _repacking {} ;# non-null => _packComponents pending
+}
+
+#
+# Provide a lowercased access method for the Selectionbox class.
+#
+proc ::iwidgets::selectionbox {pathName args} {
+ uplevel ::iwidgets::Selectionbox $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Selectionbox.itemsLabel Items widgetDefault
+option add *Selectionbox.selectionLabel Selection widgetDefault
+option add *Selectionbox.width 260 widgetDefault
+option add *Selectionbox.height 320 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::constructor {args} {
+ #
+ # Set the borderwidth to zero and add width and height options
+ # back to the hull.
+ #
+ component hull configure -borderwidth 0
+ itk_option add hull.width hull.height
+
+ #
+ # Create the child site widget.
+ #
+ itk_component add -protected sbchildsite {
+ frame $itk_interior.sbchildsite
+ }
+
+ #
+ # Create the items list.
+ #
+ itk_component add items {
+ iwidgets::Scrolledlistbox $itk_interior.items -selectmode single \
+ -visibleitems 20x10 -labelpos nw -vscrollmode static \
+ -hscrollmode none
+ } {
+ usual
+ keep -dblclickcommand -exportselection
+
+ rename -labeltext -itemslabel itemsLabel Text
+ rename -selectioncommand -itemscommand itemsCommand Command
+ }
+ configure -itemscommand [itcl::code $this selectitem]
+
+ #
+ # Create the selection entry.
+ #
+ itk_component add selection {
+ iwidgets::Entryfield $itk_interior.selection -labelpos nw
+ } {
+ usual
+
+ keep -exportselection
+
+ rename -labeltext -selectionlabel selectionLabel Text
+ rename -command -selectioncommand selectionCommand Command
+ }
+
+ #
+ # Set the interior to the childsite for derived classes.
+ #
+ set itk_interior $itk_component(sbchildsite)
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+
+ #
+ # When idle, pack the components.
+ #
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::destructor {} {
+ if {$_repacking != ""} {after cancel $_repacking}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -childsitepos
+#
+# Specifies the position of the child site in the selection box.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Selectionbox::childsitepos {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -margin
+#
+# Specifies distance between the items list and selection entry.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Selectionbox::margin {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -itemson
+#
+# Specifies whether or not to display the items list.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Selectionbox::itemson {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -selectionon
+#
+# Specifies whether or not to display the selection entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Selectionbox::selectionon {
+ _packComponents
+}
+
+# ------------------------------------------------------------------
+# OPTION: -width
+#
+# Specifies the width of the hull. The value may be specified in
+# any of the forms acceptable to Tk_GetPixels. A value of zero
+# causes the width to be adjusted to the required value based on
+# the size requests of the components. Otherwise, the width is
+# fixed.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Selectionbox::width {
+ #
+ # The width option was added to the hull in the constructor.
+ # So, any width value given is passed automatically to the
+ # hull. All we have to do is play with the propagation.
+ #
+ if {$itk_option(-width) != 0} {
+ set propagate 0
+ } else {
+ set propagate 1
+ }
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $itk_component(hull)] != $propagate} {
+ grid propagate $itk_component(hull) $propagate
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -height
+#
+# Specifies the height of the hull. The value may be specified in
+# any of the forms acceptable to Tk_GetPixels. A value of zero
+# causes the height to be adjusted to the required value based on
+# the size requests of the components. Otherwise, the height is
+# fixed.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Selectionbox::height {
+ #
+ # The height option was added to the hull in the constructor.
+ # So, any height value given is passed automatically to the
+ # hull. All we have to do is play with the propagation.
+ #
+ if {$itk_option(-height) != 0} {
+ set propagate 0
+ } else {
+ set propagate 1
+ }
+
+ #
+ # Due to a bug in the tk4.2 grid, we have to check the
+ # propagation before setting it. Setting it to the same
+ # value it already is will cause it to toggle.
+ #
+ if {[grid propagate $itk_component(hull)] != $propagate} {
+ grid propagate $itk_component(hull) $propagate
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Returns the path name of the child site widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::childsite {} {
+ return $itk_component(sbchildsite)
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Returns the current selection.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::get {} {
+ return [$itk_component(selection) get]
+}
+
+# ------------------------------------------------------------------
+# METHOD: curselection
+#
+# Returns the current selection index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::curselection {} {
+ return [$itk_component(items) curselection]
+}
+
+# ------------------------------------------------------------------
+# METHOD: clear component
+#
+# Delete the contents of either the selection entry widget or items
+# list.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::clear {component} {
+ switch $component {
+ selection {
+ $itk_component(selection) clear
+ }
+
+ items {
+ delete 0 end
+ }
+
+ default {
+ error "bad clear argument \"$component\": should be\
+ selection or items"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert component index args
+#
+# Insert element(s) into either the selection or items list widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::insert {component index args} {
+ switch $component {
+ selection {
+ eval $itk_component(selection) insert $index $args
+ }
+
+ items {
+ eval $itk_component(items) insert $index $args
+ }
+
+ default {
+ error "bad insert argument \"$component\": should be\
+ selection or items"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete first ?last?
+#
+# Delete one or more elements from the items list box. The default
+# is to delete by indexed range. If an item is to be removed by name,
+# it must be preceeded by the keyword "item". Only index numbers can
+# be used to delete a range of items.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::delete {first {last {}}} {
+ set first [index $first]
+
+ if {$last != {}} {
+ set last [index $last]
+ } else {
+ set last $first
+ }
+
+ if {$first <= $last} {
+ eval $itk_component(items) delete $first $last
+ } else {
+ error "first index must not be greater than second"
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: size
+#
+# Returns a decimal string indicating the total number of elements
+# in the items list.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::size {} {
+ return [$itk_component(items) size]
+}
+
+# ------------------------------------------------------------------
+# METHOD: scan option args
+#
+# Implements scanning on items list.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::scan {option args} {
+ eval $itk_component(items) scan $option $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: nearest y
+#
+# Returns the index to the nearest listbox item given a y coordinate.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::nearest {y} {
+ return [$itk_component(items) nearest $y]
+}
+
+# ------------------------------------------------------------------
+# METHOD: index index
+#
+# Returns the decimal string giving the integer index corresponding
+# to index.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::index {index} {
+ return [$itk_component(items) index $index]
+}
+
+# ------------------------------------------------------------------
+# METHOD: selection option args
+#
+# Adjusts the selection within the items list.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::selection {option args} {
+ eval $itk_component(items) selection $option $args
+
+ selectitem
+}
+
+# ------------------------------------------------------------------
+# METHOD: selectitem
+#
+# Replace the selection entry field contents with the currently
+# selected items value.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::selectitem {} {
+ $itk_component(selection) clear
+ set numSelected [$itk_component(items) selecteditemcount]
+
+ if {$numSelected == 1} {
+ $itk_component(selection) insert end \
+ [$itk_component(items) getcurselection]
+ } elseif {$numSelected > 1} {
+ $itk_component(selection) insert end \
+ [lindex [$itk_component(items) getcurselection] 0]
+ }
+
+ $itk_component(selection) icursor end
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _packComponents ?when?
+#
+# Pack the selection, items, and child site widgets based on options.
+# If "when" is "now", the change is applied immediately. If it is
+# "later" or it is not specified, then the change is applied later,
+# when the application is idle.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectionbox::_packComponents {{when later}} {
+ if {$when == "later"} {
+ if {$_repacking == ""} {
+ set _repacking [after idle [itcl::code $this _packComponents now]]
+ }
+ return
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ set _repacking ""
+
+ set parent [winfo parent $itk_component(sbchildsite)]
+ set margin [winfo pixels $itk_component(hull) $itk_option(-margin)]
+
+ switch $itk_option(-childsitepos) {
+ n {
+ grid $itk_component(sbchildsite) -row 0 -column 0 \
+ -sticky nsew -rowspan 1
+ grid $itk_component(items) -row 1 -column 0 -sticky nsew
+ grid $itk_component(selection) -row 3 -column 0 -sticky ew
+
+ grid rowconfigure $parent 0 -weight 0 -minsize 0
+ grid rowconfigure $parent 1 -weight 1 -minsize 0
+ grid rowconfigure $parent 2 -weight 0 -minsize $margin
+ grid rowconfigure $parent 3 -weight 0 -minsize 0
+
+ grid columnconfigure $parent 0 -weight 1 -minsize 0
+ grid columnconfigure $parent 1 -weight 0 -minsize 0
+ }
+
+ w {
+ grid $itk_component(sbchildsite) -row 0 -column 0 \
+ -sticky nsew -rowspan 3
+ grid $itk_component(items) -row 0 -column 1 -sticky nsew
+ grid $itk_component(selection) -row 2 -column 1 -sticky ew
+
+ grid rowconfigure $parent 0 -weight 1 -minsize 0
+ grid rowconfigure $parent 1 -weight 0 -minsize $margin
+ grid rowconfigure $parent 2 -weight 0 -minsize 0
+ grid rowconfigure $parent 3 -weight 0 -minsize 0
+
+ grid columnconfigure $parent 0 -weight 0 -minsize 0
+ grid columnconfigure $parent 1 -weight 1 -minsize 0
+ }
+
+ s {
+ grid $itk_component(items) -row 0 -column 0 -sticky nsew
+ grid $itk_component(selection) -row 2 -column 0 -sticky ew
+ grid $itk_component(sbchildsite) -row 3 -column 0 \
+ -sticky nsew -rowspan 1
+
+ grid rowconfigure $parent 0 -weight 1 -minsize 0
+ grid rowconfigure $parent 1 -weight 0 -minsize $margin
+ grid rowconfigure $parent 2 -weight 0 -minsize 0
+ grid rowconfigure $parent 3 -weight 0 -minsize 0
+
+ grid columnconfigure $parent 0 -weight 1 -minsize 0
+ grid columnconfigure $parent 1 -weight 0 -minsize 0
+ }
+
+ e {
+ grid $itk_component(items) -row 0 -column 0 -sticky nsew
+ grid $itk_component(selection) -row 2 -column 0 -sticky ew
+ grid $itk_component(sbchildsite) -row 0 -column 1 \
+ -sticky nsew -rowspan 3
+
+ grid rowconfigure $parent 0 -weight 1 -minsize 0
+ grid rowconfigure $parent 1 -weight 0 -minsize $margin
+ grid rowconfigure $parent 2 -weight 0 -minsize 0
+ grid rowconfigure $parent 3 -weight 0 -minsize 0
+
+ grid columnconfigure $parent 0 -weight 1 -minsize 0
+ grid columnconfigure $parent 1 -weight 0 -minsize 0
+ }
+
+ center {
+ grid $itk_component(items) -row 0 -column 0 -sticky nsew
+ grid $itk_component(sbchildsite) -row 1 -column 0 \
+ -sticky nsew -rowspan 1
+ grid $itk_component(selection) -row 3 -column 0 -sticky ew
+
+ grid rowconfigure $parent 0 -weight 1 -minsize 0
+ grid rowconfigure $parent 1 -weight 0 -minsize 0
+ grid rowconfigure $parent 2 -weight 0 -minsize $margin
+ grid rowconfigure $parent 3 -weight 0 -minsize 0
+
+ grid columnconfigure $parent 0 -weight 1 -minsize 0
+ grid columnconfigure $parent 1 -weight 0 -minsize 0
+ }
+
+ default {
+ error "bad childsitepos option \"$itk_option(-childsitepos)\":\
+ should be n, e, s, w, or center"
+ }
+ }
+
+ if {$itk_option(-itemson)} {
+ } else {
+ grid forget $itk_component(items)
+ }
+
+ if {$itk_option(-selectionon)} {
+ } else {
+ grid forget $itk_component(selection)
+ }
+
+ raise $itk_component(sbchildsite)
+}
+
diff --git a/iwidgets/generic/selectiondialog.itk b/iwidgets/generic/selectiondialog.itk
new file mode 100644
index 00000000000..076d8880195
--- /dev/null
+++ b/iwidgets/generic/selectiondialog.itk
@@ -0,0 +1,233 @@
+#
+# Selectiondialog
+# ----------------------------------------------------------------------
+# Implements a selection box similar to the OSF/Motif standard selection
+# dialog composite widget. The Selectiondialog is derived from the
+# Dialog class and is composed of a SelectionBox with attributes to
+# manipulate the dialog buttons.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Selectiondialog {
+ keep -activebackground -activerelief -background -borderwidth -cursor \
+ -elementborderwidth -foreground -highlightcolor -highlightthickness \
+ -insertbackground -insertborderwidth -insertofftime -insertontime \
+ -insertwidth -jump -labelfont -modality -selectbackground \
+ -selectborderwidth -selectforeground -textbackground -textfont \
+ -troughcolor
+}
+
+# ------------------------------------------------------------------
+# SELECTIONDIALOG
+# ------------------------------------------------------------------
+itcl::class iwidgets::Selectiondialog {
+ inherit iwidgets::Dialog
+
+ constructor {args} {}
+
+ public method childsite {}
+ public method get {}
+ public method curselection {}
+ public method clear {component}
+ public method insert {component index args}
+ public method delete {first {last {}}}
+ public method size {}
+ public method scan {option args}
+ public method nearest {y}
+ public method index {index}
+ public method selection {option args}
+ public method selectitem {}
+}
+
+#
+# Provide a lowercased access method for the Selectiondialog class.
+#
+proc ::iwidgets::selectiondialog {pathName args} {
+ uplevel ::iwidgets::Selectiondialog $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Selectiondialog.title "Selection Dialog" widgetDefault
+option add *Selectiondialog.master "." widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::constructor {args} {
+ #
+ # Set the borderwidth to zero.
+ #
+ component hull configure -borderwidth 0
+
+ #
+ # Instantiate a selection box widget.
+ #
+ itk_component add selectionbox {
+ iwidgets::Selectionbox $itk_interior.selectionbox \
+ -dblclickcommand [itcl::code $this invoke]
+ } {
+ usual
+
+ keep -childsitepos -exportselection -itemscommand -itemslabel \
+ -itemson -selectionlabel -selectionon -selectioncommand
+ }
+ configure -itemscommand [itcl::code $this selectitem]
+
+ pack $itk_component(selectionbox) -fill both -expand yes
+ set itk_interior [$itk_component(selectionbox) childsite]
+
+ hide Help
+
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::childsite {} {
+ return [$itk_component(selectionbox) childsite]
+}
+
+# ------------------------------------------------------------------
+# METHOD: get
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::get {} {
+ return [$itk_component(selectionbox) get]
+}
+
+# ------------------------------------------------------------------
+# METHOD: curselection
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::curselection {} {
+ return [$itk_component(selectionbox) curselection]
+}
+
+# ------------------------------------------------------------------
+# METHOD: clear component
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::clear {component} {
+ $itk_component(selectionbox) clear $component
+
+ return
+}
+
+# ------------------------------------------------------------------
+# METHOD: insert component index args
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::insert {component index args} {
+ eval $itk_component(selectionbox) insert $component $index $args
+
+ return
+}
+
+# ------------------------------------------------------------------
+# METHOD: delete first ?last?
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::delete {first {last {}}} {
+ $itk_component(selectionbox) delete $first $last
+
+ return
+}
+
+# ------------------------------------------------------------------
+# METHOD: size
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::size {} {
+ return [$itk_component(selectionbox) size]
+}
+
+# ------------------------------------------------------------------
+# METHOD: scan option args
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::scan {option args} {
+ return [eval $itk_component(selectionbox) scan $option $args]
+}
+
+# ------------------------------------------------------------------
+# METHOD: nearest y
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::nearest {y} {
+ return [$itk_component(selectionbox) nearest $y]
+}
+
+# ------------------------------------------------------------------
+# METHOD: index index
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::index {index} {
+ return [$itk_component(selectionbox) index $index]
+}
+
+# ------------------------------------------------------------------
+# METHOD: selection option args
+#
+# Thinwrapped method of selection box class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::selection {option args} {
+ eval $itk_component(selectionbox) selection $option $args
+}
+
+# ------------------------------------------------------------------
+# METHOD: selectitem
+#
+# Set the default button to ok and select the item.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Selectiondialog::selectitem {} {
+ default OK
+ $itk_component(selectionbox) selectitem
+}
+
diff --git a/iwidgets/generic/shell.itk b/iwidgets/generic/shell.itk
new file mode 100644
index 00000000000..85ebfbc7cb9
--- /dev/null
+++ b/iwidgets/generic/shell.itk
@@ -0,0 +1,375 @@
+# Shell
+# ----------------------------------------------------------------------
+# This class is implements a shell which is a top level widget
+# giving a childsite and providing activate, deactivate, and center
+# methods.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com
+# Kris Raney EMAIL: kraney@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1996 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 Shell {
+ keep -background -cursor -modality
+}
+
+# ------------------------------------------------------------------
+# SHELL
+# ------------------------------------------------------------------
+itcl::class iwidgets::Shell {
+ inherit itk::Toplevel
+
+ constructor {args} {}
+
+ itk_option define -master master Window ""
+ itk_option define -modality modality Modality none
+ itk_option define -padx padX Pad 0
+ itk_option define -pady padY Pad 0
+ itk_option define -width width Width 0
+ itk_option define -height height Height 0
+
+ public method childsite {}
+ public method activate {}
+ public method deactivate {args}
+ public method center {{widget {}}}
+
+ private variable _result {} ;# Resultant value for modal activation.
+ private variable _busied {} ;# List of busied top level widgets.
+
+ common grabstack {}
+ common _wait
+}
+
+#
+# Provide a lowercased access method for the Shell class.
+#
+proc ::iwidgets::shell {pathName args} {
+ uplevel ::iwidgets::Shell $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Shell::constructor {args} {
+ itk_option add hull.width hull.height
+
+ #
+ # Maintain a withdrawn state until activated.
+ #
+ wm withdraw $itk_component(hull)
+
+ #
+ # Create the user child site
+ #
+ itk_component add -protected shellchildsite {
+ frame $itk_interior.shellchildsite
+ }
+ pack $itk_component(shellchildsite) -fill both -expand yes
+
+ #
+ # Set the itk_interior variable to be the childsite for derived
+ # classes.
+ #
+ set itk_interior $itk_component(shellchildsite)
+
+ #
+ # Bind the window manager delete protocol to deactivation of the
+ # widget. This can be overridden by the user via the execution
+ # of a similar command outside the class.
+ #
+ wm protocol $itk_component(hull) WM_DELETE_WINDOW [itcl::code $this deactivate]
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -master
+#
+# Specifies the master window for the shell. The window manager is
+# informed that the shell is a transient window whose master is
+# -masterwindow.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Shell::master {}
+
+# ------------------------------------------------------------------
+# OPTION: -modality
+#
+# Specify the modality of the dialog.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Shell::modality {
+ switch $itk_option(-modality) {
+ none -
+ application -
+ global {
+ }
+
+ default {
+ error "bad modality option \"$itk_option(-modality)\":\
+ should be none, application, or global"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -padx
+#
+# Specifies a padding distance for the childsite in the X-direction.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Shell::padx {
+ pack config $itk_component(shellchildsite) -padx $itk_option(-padx)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -pady
+#
+# Specifies a padding distance for the childsite in the Y-direction.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Shell::pady {
+ pack config $itk_component(shellchildsite) -pady $itk_option(-pady)
+}
+
+# ------------------------------------------------------------------
+# OPTION: -width
+#
+# Specifies the width of the shell. The value may be specified in
+# any of the forms acceptable to Tk_GetPixels. A value of zero
+# causes the width to be adjusted to the required value based on
+# the size requests of the components placed in the childsite.
+# Otherwise, the width is fixed.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Shell::width {
+ #
+ # The width option was added to the hull in the constructor.
+ # So, any width value given is passed automatically to the
+ # hull. All we have to do is play with the propagation.
+ #
+ if {$itk_option(-width) != 0} {
+ pack propagate $itk_component(hull) no
+ } else {
+ pack propagate $itk_component(hull) yes
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -height
+#
+# Specifies the height of the shell. The value may be specified in
+# any of the forms acceptable to Tk_GetPixels. A value of zero
+# causes the height to be adjusted to the required value based on
+# the size requests of the components placed in the childsite.
+# Otherwise, the height is fixed.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Shell::height {
+ #
+ # The height option was added to the hull in the constructor.
+ # So, any height value given is passed automatically to the
+ # hull. All we have to do is play with the propagation.
+ #
+ if {$itk_option(-height) != 0} {
+ pack propagate $itk_component(hull) no
+ } else {
+ pack propagate $itk_component(hull) yes
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: childsite
+#
+# Return the pathname of the user accessible area.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Shell::childsite {} {
+ return $itk_component(shellchildsite)
+}
+
+# ------------------------------------------------------------------
+# METHOD: activate
+#
+# Display the dialog and wait based on the modality. For application
+# and global modal activations, perform a grab operation, and wait
+# for the result. The result may be returned via an argument to the
+# "deactivate" method.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Shell::activate {} {
+
+ if {[winfo ismapped $itk_component(hull)]} {
+ raise $itk_component(hull)
+ return
+ }
+
+ if {($itk_option(-master) != {}) && \
+ [winfo exists $itk_option(-master)]} {
+ wm transient $itk_component(hull) $itk_option(-master)
+ }
+
+ set _wait($this) 0
+ raise $itk_component(hull)
+ wm deiconify $itk_component(hull)
+ tkwait visibility $itk_component(hull)
+
+ # Need to flush the event loop. This line added as a result of
+ # SF ticket #227885.
+ update idletasks
+
+ if {$itk_option(-modality) == "application"} {
+ if {$grabstack != {}} {
+ grab release [lindex $grabstack end]
+ }
+
+ set err 1
+ while {$err == 1} {
+ set err [catch [list grab $itk_component(hull)]]
+ if {$err == 1} {
+ after 1000
+ }
+ }
+
+ lappend grabstack [list grab $itk_component(hull)]
+
+ tkwait variable [itcl::scope _wait($this)]
+ return $_result
+
+ } elseif {$itk_option(-modality) == "global" } {
+ if {$grabstack != {}} {
+ grab release [lindex $grabstack end]
+ }
+
+ set err 1
+ while {$err == 1} {
+ set err [catch [list grab -global $itk_component(hull)]]
+ if {$err == 1} {
+ after 1000
+ }
+ }
+
+ lappend grabstack [list grab -global $itk_component(hull)]
+
+ tkwait variable [itcl::scope _wait($this)]
+ return $_result
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: deactivate
+#
+# Deactivate the display of the dialog. The method takes an optional
+# argument to passed to the "activate" method which returns the value.
+# This is only effective for application and global modal dialogs.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Shell::deactivate {args} {
+
+ if {! [winfo ismapped $itk_component(hull)]} {
+ return
+ }
+
+ if {$itk_option(-modality) == "none"} {
+ wm withdraw $itk_component(hull)
+ } elseif {$itk_option(-modality) == "application"} {
+ grab release $itk_component(hull)
+ if {$grabstack != {}} {
+ if {[set grabstack [lreplace $grabstack end end]] != {}} {
+ eval [lindex $grabstack end]
+ }
+ }
+
+ wm withdraw $itk_component(hull)
+
+ } elseif {$itk_option(-modality) == "global"} {
+ grab release $itk_component(hull)
+ if {$grabstack != {}} {
+ if {[set grabstack [lreplace $grabstack end end]] != {}} {
+ eval [lindex $grabstack end]
+ }
+ }
+
+ wm withdraw $itk_component(hull)
+ }
+
+ if {[llength $args]} {
+ set _result $args
+ } else {
+ set _result {}
+ }
+
+ set _wait($this) 1
+ return
+}
+
+# ------------------------------------------------------------------
+# METHOD: center
+#
+# Centers the dialog with respect to another widget or the screen
+# as a whole.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Shell::center {{widget {}}} {
+ update idletasks
+
+ set hull $itk_component(hull)
+ set w [winfo width $hull]
+ set h [winfo height $hull]
+ set sh [winfo screenheight $hull] ;# display screen's height/width
+ set sw [winfo screenwidth $hull]
+
+ #
+ # User can request it centered with respect to root by passing in '{}'
+ #
+ if { $widget == "" } {
+ set reqX [expr {($sw-$w)/2}]
+ set reqY [expr {($sh-$h)/2}]
+ } else {
+ set wfudge 5 ;# wm width fudge factor
+ set hfudge 20 ;# wm height fudge factor
+ set widgetW [winfo width $widget]
+ set widgetH [winfo height $widget]
+ set reqX [expr {[winfo rootx $widget]+($widgetW-($widgetW/2))-($w/2)}]
+ set reqY [expr {[winfo rooty $widget]+($widgetH-($widgetH/2))-($h/2)}]
+
+ #
+ # Adjust for errors - if too long or too tall
+ #
+ if { ($reqX+$w+$wfudge) > $sw } { set reqX [expr {$sw-$w-$wfudge}] }
+ if { $reqX < $wfudge } { set reqX $wfudge }
+ if { ($reqY+$h+$hfudge) > $sh } { set reqY [expr {$sh-$h-$hfudge}] }
+ if { $reqY < $hfudge } { set reqY $hfudge }
+ }
+
+ wm geometry $hull +$reqX+$reqY
+}
+
diff --git a/iwidgets/generic/spindate.itk b/iwidgets/generic/spindate.itk
new file mode 100644
index 00000000000..5d431f9452d
--- /dev/null
+++ b/iwidgets/generic/spindate.itk
@@ -0,0 +1,693 @@
+# Spindate
+# ----------------------------------------------------------------------
+# Implements a Date spinner widget. A date spinner contains three
+# Spinner widgets: one Spinner for months, one SpinInt for days,
+# and one SpinInt for years. Months can be specified as abbreviated
+# strings, integers or a user-defined list. Options exist to manage to
+# behavior, appearance, and format of each component spinner.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Sue Yockey EMAIL: yockey@actc.com
+# Mark L. Ulferts mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Spindate.monthLabel "Month" widgetDefault
+option add *Spindate.dayLabel "Day" widgetDefault
+option add *Spindate.yearLabel "Year" widgetDefault
+option add *Spindate.monthWidth 4 widgetDefault
+option add *Spindate.dayWidth 4 widgetDefault
+option add *Spindate.yearWidth 4 widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Spindate {
+ keep -background -cursor -foreground -labelfont -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# SPINDATE
+# ------------------------------------------------------------------
+itcl::class iwidgets::Spindate {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -labelpos labelPos Position w
+ itk_option define -orient orient Orient vertical
+ itk_option define -monthon monthOn MonthOn true
+ itk_option define -dayon dayOn DayOn true
+ itk_option define -yearon yearOn YearOn true
+ itk_option define -datemargin dateMargin Margin 1
+ itk_option define -yeardigits yearDigits YearDigits 4
+ itk_option define -monthformat monthFormat MonthFormat integer
+
+ public {
+ method get {{format "-string"}}
+ method show {{date now}}
+ }
+
+ protected {
+ method _packDate {{when later}}
+ variable _repack {} ;# Reconfiguration flag.
+ }
+
+ private {
+ method _lastDay {month year}
+ method _spinMonth {direction}
+ method _spinDay {direction}
+
+ variable _monthFormatStr "%m"
+ variable _yearFormatStr "%Y"
+ variable _interior
+ }
+}
+
+#
+# Provide a lowercased access method for the Spindate class.
+#
+proc ::iwidgets::spindate {pathName args} {
+ uplevel ::iwidgets::Spindate $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spindate::constructor {args} {
+ set _interior $itk_interior
+
+ set clicks [clock seconds]
+
+ #
+ # Create Month Spinner
+ #
+ itk_component add month {
+ iwidgets::Spinner $itk_interior.month -fixed 2 -justify right \
+ -decrement [itcl::code $this _spinMonth -1] \
+ -increment [itcl::code $this _spinMonth 1]
+ } {
+ keep -background -cursor -arroworient -foreground \
+ -labelfont -labelmargin -relief -textbackground \
+ -textfont -repeatdelay -repeatinterval
+
+ rename -labeltext -monthlabel monthLabel Text
+ rename -width -monthwidth monthWidth Width
+ }
+
+ #
+ # Take off the default bindings for selction and motion.
+ #
+ bind [$itk_component(month) component entry] <1> {break}
+ bind [$itk_component(month) component entry] <Button1-Motion> {break}
+
+ #
+ # Create Day Spinner
+ #
+ itk_component add day {
+ iwidgets::Spinint $itk_interior.day -fixed 2 -justify right \
+ -decrement [itcl::code $this _spinDay -1] \
+ -increment [itcl::code $this _spinDay 1]
+ } {
+ keep -background -cursor -arroworient -foreground \
+ -labelfont -labelmargin -relief -textbackground \
+ -textfont -repeatdelay -repeatinterval
+
+ rename -labeltext -daylabel dayLabel Text
+ rename -width -daywidth dayWidth Width
+ }
+
+ #
+ # Take off the default bindings for selction and motion.
+ #
+ bind [$itk_component(day) component entry] <1> {break}
+ bind [$itk_component(day) component entry] <Button1-Motion> {break}
+
+ #
+ # Create Year Spinner
+ #
+ itk_component add year {
+ iwidgets::Spinint $itk_interior.year -fixed 2 -justify right \
+ -range {1900 3000}
+ } {
+ keep -background -cursor -arroworient -foreground \
+ -labelfont -labelmargin -relief -textbackground \
+ -textfont -repeatdelay -repeatinterval
+
+ rename -labeltext -yearlabel yearLabel Text
+ rename -width -yearwidth yearWidth Width
+ }
+
+ #
+ # Take off the default bindings for selction and motion.
+ #
+ bind [$itk_component(year) component entry] <1> {break}
+ bind [$itk_component(year) component entry] <Button1-Motion> {break}
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+
+ #
+ # Show the current date.
+ #
+ show now
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spindate::destructor {} {
+ if {$_repack != ""} {after cancel $_repack}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -labelpos
+#
+# Specifies the location of all 3 spinners' labels.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spindate::labelpos {
+ switch $itk_option(-labelpos) {
+ n {
+ $itk_component(month) configure -labelpos n
+ $itk_component(day) configure -labelpos n
+ $itk_component(year) configure -labelpos n
+
+ #
+ # Un-align labels
+ #
+ $itk_component(month) configure -labelmargin 1
+ $itk_component(day) configure -labelmargin 1
+ $itk_component(year) configure -labelmargin 1
+ }
+
+ s {
+ $itk_component(month) configure -labelpos s
+ $itk_component(day) configure -labelpos s
+ $itk_component(year) configure -labelpos s
+
+ #
+ # Un-align labels
+ #
+ $itk_component(month) configure -labelmargin 1
+ $itk_component(day) configure -labelmargin 1
+ $itk_component(year) configure -labelmargin 1
+ }
+
+ w {
+ $itk_component(month) configure -labelpos w
+ $itk_component(day) configure -labelpos w
+ $itk_component(year) configure -labelpos w
+ }
+
+ e {
+ $itk_component(month) configure -labelpos e
+ $itk_component(day) configure -labelpos e
+ $itk_component(year) configure -labelpos e
+
+ #
+ # Un-align labels
+ #
+ $itk_component(month) configure -labelmargin 1
+ $itk_component(day) configure -labelmargin 1
+ $itk_component(year) configure -labelmargin 1
+ }
+
+ default {
+ error "bad labelpos option \"$itk_option(-labelpos)\",\
+ should be n, s, w or e"
+ }
+ }
+
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -orient
+#
+# Specifies the orientation of the 3 spinners for Month, Day
+# and year.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spindate::orient {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -monthon
+#
+# Specifies whether or not to display the month spinner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spindate::monthon {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -dayon
+#
+# Specifies whether or not to display the day spinner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spindate::dayon {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -yearon
+#
+# Specifies whether or not to display the year spinner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spindate::yearon {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -datemargin
+#
+# Specifies the margin space between the month and day spinners
+# and the day and year spinners.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spindate::datemargin {
+ _packDate
+}
+
+# ------------------------------------------------------------------
+# OPTION: -yeardigits
+#
+# Number of digits for year display, 2 or 4
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spindate::yeardigits {
+ set clicks [clock seconds]
+
+ switch $itk_option(-yeardigits) {
+ "2" {
+ $itk_component(year) configure -width 2 -fixed 2
+ $itk_component(year) clear
+ $itk_component(year) insert 0 [clock format $clicks -format "%y"]
+ set _yearFormatStr "%y"
+ }
+
+ "4" {
+ $itk_component(year) configure -width 4 -fixed 4
+ $itk_component(year) clear
+ $itk_component(year) insert 0 [clock format $clicks -format "%Y"]
+ set _yearFormatStr "%Y"
+ }
+
+ default {
+ error "bad yeardigits option \"$itk_option(-yeardigits)\",\
+ should be 2 or 4"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -monthformat
+#
+# Format of month display, integers (1-12) or brief strings (Jan -
+# Dec), or full strings (January - December).
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spindate::monthformat {
+ set clicks [clock seconds]
+
+ if {$itk_option(-monthformat) == "brief"} {
+ $itk_component(month) configure -width 3 -fixed 3
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $clicks -format "%b"]
+ set _monthFormatStr "%b"
+
+ } elseif {$itk_option(-monthformat) == "full"} {
+ $itk_component(month) configure -width 9 -fixed 9
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $clicks -format "%B"]
+ set _monthFormatStr "%B"
+
+ } elseif {$itk_option(-monthformat) == "integer"} {
+ $itk_component(month) configure -width 2 -fixed 2
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $clicks -format "%m"]
+ set _monthFormatStr "%m"
+
+ } else {
+ error "bad monthformat option\
+ \"$itk_option(-monthformat)\", should be\
+ \"integer\", \"brief\" or \"full\""
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: get ?format?
+#
+# Return the current contents of the spindate widget in one of
+# two formats string or as an integer clock value using the -string
+# and -clicks options respectively. The default is by string.
+# Reference the clock command for more information on obtaining dates
+# and their formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spindate::get {{format "-string"}} {
+ set month [$itk_component(month) get]
+ set day [$itk_component(day) get]
+ set year [$itk_component(year) get]
+
+ if {[regexp {[0-9]+} $month]} {
+ set datestr "$month/$day/$year"
+ } else {
+ set datestr "$day $month $year"
+ }
+
+ switch -- $format {
+ "-string" {
+ return $datestr
+ }
+ "-clicks" {
+ return [clock scan $datestr]
+ }
+ default {
+ error "bad format option \"$format\":\
+ should be -string or -clicks"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: show date
+#
+# Changes the currently displayed date to be that of the date
+# argument. The date may be specified either as a string or an
+# integer clock value. Reference the clock command for more
+# information on obtaining dates and their formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spindate::show {{date "now"}} {
+ #
+ # Convert the date to a clock clicks value.
+ #
+ if {$date == "now"} {
+ set seconds [clock seconds]
+ } else {
+ if {[catch {clock format $date}] == 0} {
+ set seconds $date
+ } elseif {[catch {set seconds [clock scan $date]}] != 0} {
+ error "bad date: \"$date\", must be a valid date\
+ string, clock clicks value or the keyword now"
+ }
+ }
+
+ #
+ # Display the month based on the -monthformat option.
+ #
+ switch $itk_option(-monthformat) {
+ "brief" {
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $seconds -format "%b"]
+ }
+ "full" {
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $seconds -format "%B"]
+ }
+ "integer" {
+ $itk_component(month) delete 0 end
+ $itk_component(month) insert 0 [clock format $seconds -format "%m"]
+ }
+ }
+
+ #
+ # Display the day.
+ #
+ $itk_component(day) delete 0 end
+ $itk_component(day) insert end [clock format $seconds -format "%d"]
+
+ #
+ # Display the year based on the -yeardigits option.
+ #
+ switch $itk_option(-yeardigits) {
+ "2" {
+ $itk_component(year) delete 0 end
+ $itk_component(year) insert 0 [clock format $seconds -format "%y"]
+ }
+
+ "4" {
+ $itk_component(year) delete 0 end
+ $itk_component(year) insert 0 [clock format $seconds -format "%Y"]
+ }
+ }
+
+ return
+}
+
+# ----------------------------------------------------------------
+# PRIVATE METHOD: _spinMonth direction
+#
+# Increment or decrement month value. We need to get the values
+# for all three fields so we can make sure the day agrees with
+# the month. Should the current day be greater than the day for
+# the spun month, then the day is set to the last day for the
+# new month.
+# ----------------------------------------------------------------
+itcl::body iwidgets::Spindate::_spinMonth {direction} {
+ set month [$itk_component(month) get]
+ set day [$itk_component(day) get]
+ set year [$itk_component(year) get]
+
+ #
+ # There appears to be a bug in the Tcl clock command in that it
+ # can't scan a date like "12/31/1999 1 month" or any other date with
+ # a year above 2000, but it has no problem scanning "07/01/1998 1 month".
+ # So, we're going to play a game and increment by days until this
+ # is fixed in Tcl.
+ #
+ if {$direction == 1} {
+ set incrdays 32
+ set day 01
+ } else {
+ set incrdays -28
+ set day 28
+ }
+
+ if {[regexp {[0-9]+} $month]} {
+ set clicks [clock scan "$month/$day/$year $incrdays day"]
+ } else {
+ set clicks [clock scan "$day $month $year $incrdays day"]
+ }
+
+ $itk_component(month) clear
+ $itk_component(month) insert 0 \
+ [clock format $clicks -format $_monthFormatStr]
+
+ set currday [$itk_component(day) get]
+ set lastday [_lastDay [$itk_component(month) get] $year]
+
+ if {$currday > $lastday} {
+ $itk_component(day) clear
+ $itk_component(day) insert end $lastday
+ }
+}
+
+# ----------------------------------------------------------------
+# PRIVATE METHOD: _spinDay direction
+#
+# Increment or decrement day value. If the previous day was the
+# first, then set the new day to the last day for the current
+# month. If it was the last day of the month, change it to the
+# first. Otherwise, spin it to the next day.
+# ----------------------------------------------------------------
+itcl::body iwidgets::Spindate::_spinDay {direction} {
+ set month [$itk_component(month) get]
+ set day [$itk_component(day) get]
+ set year [$itk_component(year) get]
+ set lastday [_lastDay $month $year]
+ set currclicks [get -clicks]
+
+ $itk_component(day) delete 0 end
+
+ if {(($day == "01") || ($day == "1")) && ($direction == -1)} {
+ $itk_component(day) insert 0 $lastday
+ return
+ }
+
+ if {($day == $lastday) && ($direction == 1)} {
+ $itk_component(day) insert 0 "01"
+ return
+ }
+
+ set clicks [clock scan "$direction day" -base $currclicks]
+ $itk_component(day) insert 0 [clock format $clicks -format "%d"]
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _packDate when
+#
+# Pack the components of the date spinner. If "when" is "now", the
+# change is applied immediately. If it is "later" or it is not
+# specified, then the change is applied later, when the application
+# is idle.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spindate::_packDate {{when later}} {
+ if {$when == "later"} {
+ if {$_repack == ""} {
+ set _repack [after idle [itcl::code $this _packDate now]]
+ }
+ return
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ #
+ # Turn off the minsizes for all the rows and columns.
+ #
+ for {set i 0} {$i < 5} {incr i} {
+ grid rowconfigure $_interior $i -minsize 0
+ grid columnconfigure $_interior $i -minsize 0
+ }
+
+ set _repack ""
+
+ #
+ # Based on the orientation, use the grid to place the components into
+ # the proper rows and columns.
+ #
+ switch $itk_option(-orient) {
+ vertical {
+ set row -1
+
+ if {$itk_option(-monthon)} {
+ grid $itk_component(month) -row [incr row] -column 0 \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(month)
+ }
+
+ if {$itk_option(-dayon)} {
+ if {$itk_option(-dayon)} {
+ grid rowconfigure $_interior [incr row] \
+ -minsize $itk_option(-datemargin)
+ }
+
+ grid $itk_component(day) -row [incr row] -column 0 \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(day)
+ }
+
+ if {$itk_option(-yearon)} {
+ if {$itk_option(-monthon) || $itk_option(-dayon)} {
+ grid rowconfigure $_interior [incr row] \
+ -minsize $itk_option(-datemargin)
+ }
+
+ grid $itk_component(year) -row [incr row] -column 0 \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(year)
+ }
+
+ if {$itk_option(-labelpos) == "w"} {
+ iwidgets::Labeledwidget::alignlabels $itk_component(month) \
+ $itk_component(day) $itk_component(year)
+ }
+ }
+
+ horizontal {
+ set column -1
+
+ if {$itk_option(-monthon)} {
+ grid $itk_component(month) -row 0 -column [incr column] \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(month)
+ }
+
+ if {$itk_option(-dayon)} {
+ if {$itk_option(-monthon)} {
+ grid columnconfigure $_interior [incr column] \
+ -minsize $itk_option(-datemargin)
+ }
+
+ grid $itk_component(day) -row 0 -column [incr column] \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(day)
+ }
+
+ if {$itk_option(-yearon)} {
+ if {$itk_option(-monthon) || $itk_option(-dayon)} {
+ grid columnconfigure $_interior [incr column] \
+ -minsize $itk_option(-datemargin)
+ }
+
+ grid $itk_component(year) -row 0 -column [incr column] \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(year)
+ }
+
+ #
+ # Un-align labels.
+ #
+ $itk_component(month) configure -labelmargin 1
+ $itk_component(day) configure -labelmargin 1
+ $itk_component(year) configure -labelmargin 1
+ }
+
+ default {
+ error "bad orient option \"$itk_option(-orient)\", should\
+ be \"vertical\" or \"horizontal\""
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _lastDay month year
+#
+# Internal method which determines the last day of the month for
+# the given month and year. We start at 28 and go forward till
+# we fail. Crude but effective.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spindate::_lastDay {month year} {
+ set lastone 28
+
+ for {set lastone 28} {$lastone < 32} {incr lastone} {
+ if {[regexp {[0-9]+} $month]} {
+ if {[catch {clock scan "$month/[expr {$lastone + 1}]/$year"}] != 0} {
+ return $lastone
+ }
+ } else {
+ if {[catch {clock scan "[expr {$lastone + 1}] $month $year"}] != 0} {
+ return $lastone
+ }
+ }
+ }
+}
diff --git a/iwidgets/generic/spinint.itk b/iwidgets/generic/spinint.itk
new file mode 100644
index 00000000000..9930b92343a
--- /dev/null
+++ b/iwidgets/generic/spinint.itk
@@ -0,0 +1,237 @@
+# Spinint
+# ----------------------------------------------------------------------
+# Implements an integer spinner widget. It inherits basic spinner
+# functionality from Spinner and adds specific features to create
+# an integer-only spinner.
+# Arrows may be placed horizontally or vertically.
+# User may specify an integer range and step value.
+# Spinner may be configured to wrap when min or max value is reached.
+#
+# NOTE:
+# Spinint integer values should not exceed the size of a long integer.
+# For a 32 bit long the integer range is -2147483648 to 2147483647.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Sue Yockey Phone: (214) 519-2517
+# E-mail: syockey@spd.dsccc.com
+# yockey@acm.org
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Spinint {
+ keep -background -borderwidth -cursor -foreground -highlightcolor \
+ -highlightthickness -insertbackground -insertborderwidth \
+ -insertofftime -insertontime -insertwidth -labelfont \
+ -selectbackground -selectborderwidth -selectforeground \
+ -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# SPININT
+# ------------------------------------------------------------------
+itcl::class iwidgets::Spinint {
+ inherit iwidgets::Spinner
+
+ constructor {args} {
+ Spinner::constructor -validate numeric
+ } {}
+
+ itk_option define -range range Range ""
+ itk_option define -step step Step 1
+ itk_option define -wrap wrap Wrap true
+
+ public method up {}
+ public method down {}
+}
+
+#
+# Provide a lowercased access method for the Spinint class.
+#
+proc ::iwidgets::spinint {pathName args} {
+ uplevel ::iwidgets::Spinint $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinint::constructor {args} {
+ eval itk_initialize $args
+
+ $itk_component(entry) delete 0 end
+
+ if {[lindex $itk_option(-range) 0] == ""} {
+ $itk_component(entry) insert 0 "0"
+ } else {
+ $itk_component(entry) insert 0 [lindex $itk_option(-range) 0]
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -range
+#
+# Set min and max values for spinner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinint::range {
+ if {$itk_option(-range) != ""} {
+ if {[llength $itk_option(-range)] != 2} {
+ error "wrong # args: should be\
+ \"$itk_component(hull) configure -range {begin end}\""
+ }
+
+ set min [lindex $itk_option(-range) 0]
+ set max [lindex $itk_option(-range) 1]
+
+ if {![regexp {^-?[0-9]+$} $min]} {
+ error "bad range option \"$min\": begin value must be\
+ an integer"
+ }
+ if {![regexp {^-?[0-9]+$} $max]} {
+ error "bad range option \"$max\": end value must be\
+ an integer"
+ }
+ if {$min > $max} {
+ error "bad option starting range \"$min\": must be less\
+ than ending: \"$max\""
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -step
+#
+# Increment spinner by step value.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinint::step {
+}
+
+# ------------------------------------------------------------------
+# OPTION: -wrap
+#
+# Specify whether spinner should wrap value if at min or max.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinint::wrap {
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: up
+#
+# Up arrow button press event. Increment value in entry.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinint::up {} {
+ set min_range [lindex $itk_option(-range) 0]
+ set max_range [lindex $itk_option(-range) 1]
+
+ set val [$itk_component(entry) get]
+ if {[lindex $itk_option(-range) 0] != ""} {
+
+ #
+ # Check boundaries.
+ #
+ if {$val >= $min_range && $val < $max_range} {
+ incr val $itk_option(-step)
+ $itk_component(entry) delete 0 end
+ $itk_component(entry) insert 0 $val
+ } else {
+ if {$itk_option(-wrap)} {
+ if {$val >= $max_range} {
+ $itk_component(entry) delete 0 end
+ $itk_component(entry) insert 0 $min_range
+ } elseif {$val < $min_range} {
+ $itk_component(entry) delete 0 end
+ $itk_component(entry) insert 0 $min_range
+ } else {
+ uplevel #0 $itk_option(-invalid)
+ }
+ } else {
+ uplevel #0 $itk_option(-invalid)
+ }
+ }
+ } else {
+
+ #
+ # No boundaries.
+ #
+ incr val $itk_option(-step)
+ $itk_component(entry) delete 0 end
+ $itk_component(entry) insert 0 $val
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: down
+#
+# Down arrow button press event. Decrement value in entry.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinint::down {} {
+ set min_range [lindex $itk_option(-range) 0]
+ set max_range [lindex $itk_option(-range) 1]
+
+ set val [$itk_component(entry) get]
+ if {[lindex $itk_option(-range) 0] != ""} {
+
+ #
+ # Check boundaries.
+ #
+ if {$val > $min_range && $val <= $max_range} {
+ incr val -$itk_option(-step)
+ $itk_component(entry) delete 0 end
+ $itk_component(entry) insert 0 $val
+ } else {
+ if {$itk_option(-wrap)} {
+ if {$val <= $min_range} {
+ $itk_component(entry) delete 0 end
+ $itk_component(entry) insert 0 $max_range
+ } elseif {$val > $max_range} {
+ $itk_component(entry) delete 0 end
+ $itk_component(entry) insert 0 $max_range
+ } else {
+ uplevel #0 $itk_option(-invalid)
+ }
+ } else {
+ uplevel #0 $itk_option(-invalid)
+ }
+ }
+ } else {
+
+ #
+ # No boundaries.
+ #
+ incr val -$itk_option(-step)
+ $itk_component(entry) delete 0 end
+ $itk_component(entry) insert 0 $val
+ }
+}
diff --git a/iwidgets/generic/spinner.itk b/iwidgets/generic/spinner.itk
new file mode 100644
index 00000000000..422b065efac
--- /dev/null
+++ b/iwidgets/generic/spinner.itk
@@ -0,0 +1,448 @@
+# Spinner
+# ----------------------------------------------------------------------
+# Implements a spinner widget. The Spinner is comprised of an
+# EntryField plus up and down arrow buttons.
+# Spinner is meant to be used as a base class for creating more
+# specific spinners such as SpinInt.itk
+# Arrows may be drawn horizontally or vertically.
+# User may define arrow behavior or accept the default arrow behavior.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Sue Yockey Phone: (214) 519-2517
+# E-mail: syockey@spd.dsccc.com
+# yockey@acm.org
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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 Spinner {
+ keep -background -borderwidth -cursor -foreground -highlightcolor \
+ -highlightthickness -insertbackground -insertborderwidth \
+ -insertofftime -insertontime -insertwidth -labelfont \
+ -selectbackground -selectborderwidth -selectforeground \
+ -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# SPINNER
+# ------------------------------------------------------------------
+itcl::class iwidgets::Spinner {
+ inherit iwidgets::Entryfield
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -arroworient arrowOrient Orient vertical
+ itk_option define -textfont textFont \
+ Font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
+ itk_option define -borderwidth borderWidth BorderWidth 2
+ itk_option define -highlightthickness highlightThickness \
+ HighlightThickness 2
+ itk_option define -increment increment Command {}
+ itk_option define -decrement decrement Command {}
+ itk_option define -repeatdelay repeatDelay RepeatDelay 300
+ itk_option define -repeatinterval repeatInterval RepeatInterval 100
+ itk_option define -foreground foreground Foreground black
+
+ public method down {}
+ public method up {}
+
+ protected method _pushup {}
+ protected method _pushdown {}
+ protected method _relup {}
+ protected method _reldown {}
+ protected method _doup {rate}
+ protected method _dodown {rate}
+ protected method _up {}
+ protected method _down {}
+
+ protected method _positionArrows {{when later}}
+
+ protected variable _interior {}
+ protected variable _reposition "" ;# non-null => _positionArrows pending
+ protected variable _uptimer "" ;# non-null => _uptimer pending
+ protected variable _downtimer "" ;# non-null => _downtimer pending
+}
+
+#
+# Provide a lowercased access method for the Spinner class.
+#
+proc ::iwidgets::spinner {pathName args} {
+ uplevel ::iwidgets::Spinner $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::constructor {args} {
+ #
+ # Save off the interior for later use.
+ #
+ set _interior $itk_interior
+
+ #
+ # Create up arrow button.
+ #
+ itk_component add uparrow {
+ canvas $itk_interior.uparrow -height 10 -width 10 \
+ -relief raised -highlightthickness 0
+ } {
+ keep -background -borderwidth
+ }
+
+ #
+ # Create down arrow button.
+ #
+ itk_component add downarrow {
+ canvas $itk_interior.downarrow -height 10 -width 10 \
+ -relief raised -highlightthickness 0
+ } {
+ keep -background -borderwidth
+ }
+
+ #
+ # Add bindings for button press events on the up and down buttons.
+ #
+ bind $itk_component(uparrow) <ButtonPress-1> [itcl::code $this _pushup]
+ bind $itk_component(uparrow) <ButtonRelease-1> [itcl::code $this _relup]
+
+ bind $itk_component(downarrow) <ButtonPress-1> [itcl::code $this _pushdown]
+ bind $itk_component(downarrow) <ButtonRelease-1> [itcl::code $this _reldown]
+
+ eval itk_initialize $args
+
+ #
+ # When idle, position the arrows.
+ #
+ _positionArrows
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+
+itcl::body iwidgets::Spinner::destructor {} {
+ if {$_reposition != ""} {after cancel $_reposition}
+ if {$_uptimer != ""} {after cancel $_uptimer}
+ if {$_downtimer != ""} {after cancel $_downtimer}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -arroworient
+#
+# Place arrows vertically or horizontally .
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinner::arroworient {
+ _positionArrows
+}
+
+# ------------------------------------------------------------------
+# OPTION: -textfont
+#
+# Change font, resize arrow buttons.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinner::textfont {
+ _positionArrows
+}
+
+# ------------------------------------------------------------------
+# OPTION: -highlightthickness
+#
+# Change highlightthickness, resize arrow buttons.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinner::highlightthickness {
+ _positionArrows
+}
+
+# ------------------------------------------------------------------
+# OPTION: -borderwidth
+#
+# Change borderwidth, resize arrow buttons.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinner::borderwidth {
+ _positionArrows
+}
+
+# ------------------------------------------------------------------
+# OPTION: -increment
+#
+# Up arrow callback.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinner::increment {
+ if {$itk_option(-increment) == {}} {
+ set itk_option(-increment) [itcl::code $this up]
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -decrement
+#
+# Down arrow callback.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinner::decrement {
+ if {$itk_option(-decrement) == {}} {
+ set itk_option(-decrement) [itcl::code $this down]
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -repeatinterval
+#
+# Arrow repeat rate in milliseconds. A repeatinterval of 0 disables
+# button repeat.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinner::repeatinterval {
+ if {$itk_option(-repeatinterval) < 0} {
+ set itk_option(-repeatinterval) 0
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -repeatdelay
+#
+# Arrow repeat delay in milliseconds.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinner::repeatdelay {
+ if {$itk_option(-repeatdelay) < 0} {
+ set itk_option(-repeatdelay) 0
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -foreground
+#
+# Set the foreground color of the up and down arrows. Remember
+# to make sure the "tag" exists before setting them...
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spinner::foreground {
+
+ if { [$itk_component(uparrow) gettags up] != "" } {
+ $itk_component(uparrow) itemconfigure up \
+ -fill $itk_option(-foreground)
+ }
+
+ if { [$itk_component(downarrow) gettags down] != "" } {
+ $itk_component(downarrow) itemconfigure down \
+ -fill $itk_option(-foreground)
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: up
+#
+# Up arrow command. Meant to be overloaded by derived class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::up {} {
+}
+
+# ------------------------------------------------------------------
+# METHOD: down
+#
+# Down arrow command. Meant to be overloaded by derived class.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::down {} {
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _positionArrows ?when?
+#
+# Draw Arrows for spinner. If "when" is "now", the change is applied
+# immediately. If it is "later" or it is not specified, then the
+# change is applied later, when the application is idle.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::_positionArrows {{when later}} {
+ if {$when == "later"} {
+ if {$_reposition == ""} {
+ set _reposition [after idle [itcl::code $this _positionArrows now]]
+ }
+ return
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ set _reposition ""
+
+ set bdw [cget -borderwidth]
+
+ #
+ # Based on the orientation of the arrows, pack them accordingly and
+ # determine the width and height of the spinners. For vertical
+ # orientation, it is really tight in the y direction, so we'll take
+ # advantage of the highlightthickness. Horizontal alignment has
+ # plenty of space vertically, thus we'll ignore the thickness.
+ #
+ switch $itk_option(-arroworient) {
+ vertical {
+ grid $itk_component(uparrow) -row 0 -column 0
+ grid $itk_component(downarrow) -row 1 -column 0
+
+ set totalHgt [winfo reqheight $itk_component(entry)]
+ set spinHgt [expr {$totalHgt / 2}]
+ set spinWid [expr {round ($spinHgt * 1.6)}]
+ }
+ horizontal {
+ grid $itk_component(uparrow) -row 0 -column 0
+ grid $itk_component(downarrow) -row 0 -column 1
+
+ set spinHgt [expr {[winfo reqheight $itk_component(entry)] - \
+ (2 * [$itk_component(entry) cget -highlightthickness])}]
+ set spinWid $spinHgt
+ }
+ default {
+ error "bad orientation option \"$itk_option(-arroworient)\",\
+ should be horizontal or vertical"
+ }
+ }
+
+ #
+ # Configure the width and height of the spinners minus the borderwidth.
+ # Next delete the previous spinner polygons and create new ones.
+ #
+ $itk_component(uparrow) config \
+ -height [expr {$spinHgt - (2 * $bdw)}] \
+ -width [expr {$spinWid - (2 * $bdw)}]
+ $itk_component(uparrow) delete up
+ $itk_component(uparrow) create polygon \
+ [expr {$spinWid / 2}] $bdw \
+ [expr {$spinWid - $bdw - 1}] [expr {$spinHgt - $bdw -1}] \
+ [expr {$bdw + 1}] [expr {$spinHgt - $bdw - 1}] \
+ -fill $itk_option(-foreground) -tags up
+
+ $itk_component(downarrow) config \
+ -height [expr {$spinHgt - (2 * $bdw)}] \
+ -width [expr {$spinWid - (2 * $bdw)}]
+ $itk_component(downarrow) delete down
+ $itk_component(downarrow) create polygon \
+ [expr {$spinWid / 2}] [expr {($spinHgt - $bdw) - 1}] \
+ [expr {$bdw + 2}] [expr {$bdw + 1}] \
+ [expr {$spinWid - $bdw - 2}] [expr {$bdw + 1}] \
+ -fill $itk_option(-foreground) -tags down
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _pushup
+#
+# Up arrow button press event. Call _doup with repeatdelay.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::_pushup {} {
+ $itk_component(uparrow) config -relief sunken
+ _doup $itk_option(-repeatdelay)
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _pushdown
+#
+# Down arrow button press event. Call _dodown with repeatdelay.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::_pushdown {} {
+ $itk_component(downarrow) config -relief sunken
+ _dodown $itk_option(-repeatdelay)
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _doup
+#
+# Call _up and post to do another one after "rate" milliseconds if
+# repeatinterval > 0.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::_doup {rate} {
+ _up
+
+ if {$itk_option(-repeatinterval) > 0} {
+ set _uptimer [after $rate [itcl::code $this _doup $itk_option(-repeatinterval)]]
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _dodown
+#
+# Call _down and post to do another one after "rate" milliseconds if
+# repeatinterval > 0.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::_dodown {rate} {
+ _down
+
+ if {$itk_option(-repeatinterval) > 0} {
+ set _downtimer \
+ [after $rate [itcl::code $this _dodown $itk_option(-repeatinterval)]]
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _relup
+#
+# Up arrow button release event. Cancel pending up timer.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::_relup {} {
+ $itk_component(uparrow) config -relief raised
+
+ if {$_uptimer != ""} {
+ after cancel $_uptimer
+ set _uptimer ""
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _reldown
+#
+# Up arrow button release event. Cancel pending down timer.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::_reldown {} {
+ $itk_component(downarrow) config -relief raised
+
+ if {$_downtimer != ""} {
+ after cancel $_downtimer
+ set _downtimer ""
+ }
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _up
+#
+# Up arrow button press event. Call defined increment command.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::_up {} {
+ uplevel #0 $itk_option(-increment)
+}
+
+# ------------------------------------------------------------------
+# PRIVATE METHOD: _down
+#
+# Down arrow button press event. Call defined decrement command.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spinner::_down {} {
+ uplevel #0 $itk_option(-decrement)
+}
diff --git a/iwidgets/generic/spintime.itk b/iwidgets/generic/spintime.itk
new file mode 100644
index 00000000000..b39ede0ed51
--- /dev/null
+++ b/iwidgets/generic/spintime.itk
@@ -0,0 +1,527 @@
+# Spintime
+# ----------------------------------------------------------------------
+# Implements a Time spinner widget. A time spinner contains three
+# integer spinners: one for hours, one for minutes and one for
+# seconds. Options exist to manage to behavior, appearance, and
+# format of each component spinner.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Sue Yockey EMAIL: yockey@actc.com
+# Mark L. Ulferts mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Spintime.hourLabel "Hour" widgetDefault
+option add *Spintime.minuteLabel "Minute" widgetDefault
+option add *Spintime.secondLabel "Second" widgetDefault
+option add *Spintime.hourWidth 3 widgetDefault
+option add *Spintime.minuteWidth 3 widgetDefault
+option add *Spintime.secondWidth 3 widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Spintime {
+ keep -background -cursor -foreground -labelfont -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# SPINTIME
+# ------------------------------------------------------------------
+itcl::class iwidgets::Spintime {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -orient orient Orient vertical
+ itk_option define -labelpos labelPos Position w
+ itk_option define -houron hourOn HourOn true
+ itk_option define -minuteon minuteOn MinuteOn true
+ itk_option define -secondon secondOn SecondOn true
+ itk_option define -timemargin timeMargin Margin 1
+ itk_option define -militaryon militaryOn MilitaryOn true
+
+ public {
+ method get {{format "-string"}}
+ method show {{date now}}
+ }
+
+ protected {
+ method _packTime {{when later}}
+ method _down60 {comp}
+
+ variable _repack {} ;# Reconfiguration flag.
+ variable _interior
+ }
+}
+
+#
+# Provide a lowercased access method for the Spintime class.
+#
+proc ::iwidgets::spintime {pathName args} {
+ uplevel ::iwidgets::Spintime $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spintime::constructor {args} {
+ set _interior $itk_interior
+ set clicks [clock seconds]
+
+ #
+ # Create Hour Spinner
+ #
+ itk_component add hour {
+ iwidgets::Spinint $itk_interior.hour -fixed 2 -range {0 23} -justify right
+ } {
+ keep -background -cursor -arroworient -foreground \
+ -labelfont -labelmargin -relief -textbackground \
+ -textfont -repeatdelay -repeatinterval
+
+ rename -labeltext -hourlabel hourLabel Text
+ rename -width -hourwidth hourWidth Width
+ }
+
+ #
+ # Take off the default bindings for selction and motion.
+ #
+ bind [$itk_component(hour) component entry] <1> {break}
+ bind [$itk_component(hour) component entry] <Button1-Motion> {break}
+
+ #
+ # Create Minute Spinner
+ #
+ itk_component add minute {
+ iwidgets::Spinint $itk_interior.minute \
+ -decrement [itcl::code $this _down60 minute] \
+ -fixed 2 -range {0 59} -justify right
+ } {
+ keep -background -cursor -arroworient -foreground \
+ -labelfont -labelmargin -relief -textbackground \
+ -textfont -repeatdelay -repeatinterval
+
+ rename -labeltext -minutelabel minuteLabel Text
+ rename -width -minutewidth minuteWidth Width
+ }
+
+ #
+ # Take off the default bindings for selction and motion.
+ #
+ bind [$itk_component(minute) component entry] <1> {break}
+ bind [$itk_component(minute) component entry] <Button1-Motion> {break}
+
+ #
+ # Create Second Spinner
+ #
+ itk_component add second {
+ iwidgets::Spinint $itk_interior.second \
+ -decrement [itcl::code $this _down60 second] \
+ -fixed 2 -range {0 59} -justify right
+ } {
+ keep -background -cursor -arroworient -foreground \
+ -labelfont -labelmargin -relief -textbackground \
+ -textfont -repeatdelay -repeatinterval
+
+ rename -labeltext -secondlabel secondLabel Text
+ rename -width -secondwidth secondWidth Width
+ }
+
+ #
+ # Take off the default bindings for selction and motion.
+ #
+ bind [$itk_component(second) component entry] <1> {break}
+ bind [$itk_component(second) component entry] <Button1-Motion> {break}
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+
+ #
+ # Show the current time.
+ #
+ show now
+}
+
+# ------------------------------------------------------------------
+# DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spintime::destructor {} {
+ if {$_repack != ""} {after cancel $_repack}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -orient
+#
+# Specifies the orientation of the 3 spinners for Hour, Minute
+# and second.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spintime::orient {
+ _packTime
+}
+
+# ------------------------------------------------------------------
+# OPTION: -labelpos
+#
+# Specifies the location of all 3 spinners' labels.
+# Overloaded
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spintime::labelpos {
+ switch $itk_option(-labelpos) {
+ n {
+ $itk_component(hour) configure -labelpos n
+ $itk_component(minute) configure -labelpos n
+ $itk_component(second) configure -labelpos n
+
+ #
+ # Un-align labels
+ #
+ $itk_component(hour) configure -labelmargin 1
+ $itk_component(minute) configure -labelmargin 1
+ $itk_component(second) configure -labelmargin 1
+ }
+
+ s {
+ $itk_component(hour) configure -labelpos s
+ $itk_component(minute) configure -labelpos s
+ $itk_component(second) configure -labelpos s
+
+ #
+ # Un-align labels
+ #
+ $itk_component(hour) configure -labelmargin 1
+ $itk_component(minute) configure -labelmargin 1
+ $itk_component(second) configure -labelmargin 1
+ }
+
+ w {
+ $itk_component(hour) configure -labelpos w
+ $itk_component(minute) configure -labelpos w
+ $itk_component(second) configure -labelpos w
+ }
+
+ e {
+ $itk_component(hour) configure -labelpos e
+ $itk_component(minute) configure -labelpos e
+ $itk_component(second) configure -labelpos e
+
+ #
+ # Un-align labels
+ #
+ $itk_component(hour) configure -labelmargin 1
+ $itk_component(minute) configure -labelmargin 1
+ $itk_component(second) configure -labelmargin 1
+ }
+
+ default {
+ error "bad labelpos option \"$itk_option(-labelpos)\",\
+ should be n, s, w or e"
+ }
+ }
+
+ _packTime
+}
+
+# ------------------------------------------------------------------
+# OPTION: -houron
+#
+# Specifies whether or not to display the hour spinner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spintime::houron {
+ _packTime
+}
+
+# ------------------------------------------------------------------
+# OPTION: -minuteon
+#
+# Specifies whether or not to display the minute spinner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spintime::minuteon {
+ _packTime
+}
+
+# ------------------------------------------------------------------
+# OPTION: -secondon
+#
+# Specifies whether or not to display the second spinner.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spintime::secondon {
+ _packTime
+}
+
+
+# ------------------------------------------------------------------
+# OPTION: -timemargin
+#
+# Specifies the margin space between the hour and minute spinners
+# and the minute and second spinners.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spintime::timemargin {
+ _packTime
+}
+
+# ------------------------------------------------------------------
+# OPTION: -militaryon
+#
+# Specifies 24-hour clock or 12-hour.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Spintime::militaryon {
+ set clicks [clock seconds]
+
+ if {$itk_option(-militaryon)} {
+ $itk_component(hour) configure -range {0 23}
+ $itk_component(hour) delete 0 end
+ $itk_component(hour) insert end [clock format $clicks -format "%H"]
+ } else {
+ $itk_component(hour) configure -range {1 12}
+ $itk_component(hour) delete 0 end
+ $itk_component(hour) insert end [clock format $clicks -format "%I"]
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# METHOD: get ?format?
+#
+# Get the value of the time spinner in one of two formats string or
+# as an integer clock value using the -string and -clicks options
+# respectively. The default is by string. Reference the clock
+# command for more information on obtaining time and its formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spintime::get {{format "-string"}} {
+ set hour [$itk_component(hour) get]
+ set minute [$itk_component(minute) get]
+ set second [$itk_component(second) get]
+
+ switch -- $format {
+ "-string" {
+ return "$hour:$minute:$second"
+ }
+ "-clicks" {
+ return [clock scan "$hour:$minute:$second"]
+ }
+ default {
+ error "bad format option \"$format\":\
+ should be -string or -clicks"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: show time
+#
+# Changes the currently displayed time to be that of the time
+# argument. The time may be specified either as a string or an
+# integer clock value. Reference the clock command for more
+# information on obtaining time and its format.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spintime::show {{time "now"}} {
+ if {$time == "now"} {
+ set seconds [clock seconds]
+ } else {
+ if {[catch {clock format $time}] == 0} {
+ set seconds $time
+ } elseif {[catch {set seconds [clock scan $time]}] != 0} {
+ error "bad time: \"$time\", must be a valid time\
+ string, clock clicks value or the keyword now"
+ }
+ }
+
+ $itk_component(hour) delete 0 end
+
+ if {$itk_option(-militaryon)} {
+ scan [clock format $seconds -format "%H"] "%d" hour
+ } else {
+ scan hour [clock format $seconds -format "%I"] "%d" hour
+ }
+
+ $itk_component(hour) insert end $hour
+
+ $itk_component(minute) delete 0 end
+ scan [clock format $seconds -format "%M"] "%d" minute
+ $itk_component(minute) insert end $minute
+
+ $itk_component(second) delete 0 end
+ scan [clock format $seconds -format "%S"] "%d" seconds
+ $itk_component(second) insert end $seconds
+
+ return
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _packTime ?when?
+#
+# Pack components of time spinner. If "when" is "now", the change
+# is applied immediately. If it is "later" or it is not specified,
+# then the change is applied later, when the application is idle.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spintime::_packTime {{when later}} {
+ if {$when == "later"} {
+ if {$_repack == ""} {
+ set _repack [after idle [itcl::code $this _packTime now]]
+ }
+ return
+ } elseif {$when != "now"} {
+ error "bad option \"$when\": should be now or later"
+ }
+
+ for {set i 0} {$i < 5} {incr i} {
+ grid rowconfigure $_interior $i -minsize 0
+ grid columnconfigure $_interior $i -minsize 0
+ }
+
+ if {$itk_option(-minuteon)} {
+ set minuteon 1
+ } else {
+ set minuteon 0
+ }
+ if {$itk_option(-secondon)} {
+ set secondon 1
+ } else {
+ set secondon 0
+ }
+
+ set _repack ""
+
+ switch $itk_option(-orient) {
+ vertical {
+ set row -1
+
+ if {$itk_option(-houron)} {
+ grid $itk_component(hour) -row [incr row] -column 0 \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(hour)
+ }
+
+ if {$itk_option(-minuteon)} {
+ if {$itk_option(-houron)} {
+ grid rowconfigure $_interior [incr row] \
+ -minsize $itk_option(-timemargin)
+ }
+
+ grid $itk_component(minute) -row [incr row] -column 0 \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(minute)
+ }
+
+ if {$itk_option(-secondon)} {
+ if {$minuteon || $secondon} {
+ grid rowconfigure $_interior [incr row] \
+ -minsize $itk_option(-timemargin)
+ }
+
+ grid $itk_component(second) -row [incr row] -column 0 \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(second)
+ }
+
+ if {$itk_option(-labelpos) == "w"} {
+ iwidgets::Labeledwidget::alignlabels $itk_component(hour) \
+ $itk_component(minute) $itk_component(second)
+ }
+ }
+
+ horizontal {
+ set column -1
+
+ if {$itk_option(-houron)} {
+ grid $itk_component(hour) -row 0 -column [incr column] \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(hour)
+ }
+
+ if {$itk_option(-minuteon)} {
+ if {$itk_option(-houron)} {
+ grid columnconfigure $_interior [incr column] \
+ -minsize $itk_option(-timemargin)
+ }
+
+ grid $itk_component(minute) -row 0 -column [incr column] \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(minute)
+ }
+
+ if {$itk_option(-secondon)} {
+ if {$minuteon || $secondon} {
+ grid columnconfigure $_interior [incr column] \
+ -minsize $itk_option(-timemargin)
+ }
+
+ grid $itk_component(second) -row 0 -column [incr column] \
+ -sticky nsew
+ } else {
+ grid forget $itk_component(second)
+ }
+
+ #
+ # Un-align labels
+ #
+ $itk_component(hour) configure -labelmargin 1
+ $itk_component(minute) configure -labelmargin 1
+ $itk_component(second) configure -labelmargin 1
+ }
+
+ default {
+ error "bad orient option \"$itk_option(-orient)\", should\
+ be \"vertical\" or \"horizontal\""
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHOD: down60
+#
+# Down arrow button press event. Decrement value in the minute
+# or second entry.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Spintime::_down60 {comp} {
+ set step [$itk_component($comp) cget -step]
+ set val [$itk_component($comp) get]
+
+ incr val -$step
+ if {$val < 0} {
+ set val [expr {60-$step}]
+ }
+ $itk_component($comp) delete 0 end
+ $itk_component($comp) insert 0 $val
+}
diff --git a/iwidgets/generic/tabnotebook.itk b/iwidgets/generic/tabnotebook.itk
new file mode 100644
index 00000000000..7e8be370cf0
--- /dev/null
+++ b/iwidgets/generic/tabnotebook.itk
@@ -0,0 +1,1105 @@
+#
+# Tabnotebook Widget
+# ----------------------------------------------------------------------
+# The Tabnotebook command creates a new window (given by the pathName
+# argument) and makes it into a Tabnotebook widget. Additional options,
+# described above may be specified on the command line or in the option
+# database to configure aspects of the Tabnotebook such as its colors,
+# font, and text. The Tabnotebook command returns its pathName argument.
+# At the time this command is invoked, there must not exist a window
+# named pathName, but pathName's parent must exist.
+#
+# A Tabnotebook is a widget that contains a set of tabbed pages. It
+# displays one page from the set as the selected page. A Tab displays
+# the label for the page to which it is attached and serves as a page
+# selector. When a page's tab is selected, the page's contents are
+# displayed in the page area. The selected tab has a three-dimensional
+# effect to make it appear to float above the other tabs. The tabs are
+# displayed as a group along either the left, top, right, or bottom
+# edge. When first created a Tabnotebook has no pages. Pages may be
+# added or deleted using widget commands described below.
+#
+# A special option may be provided to the Tabnotebook. The -auto
+# option specifies whether the Tabnotebook will automatically handle
+# the unpacking and packing of pages when pages are selected. A value
+# of true sig nifies that the notebook will automatically manage it. This
+# is the default value. A value of false signifies the notebook will not
+# perform automatic switching of pages.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Bill W. Scott
+#
+# CURRENT MAINTAINER: Chad Smith --> csmith@adc.com or itclguy@yahoo.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Tabnotebook.borderWidth 2 widgetDefault
+option add *Tabnotebook.state normal widgetDefault
+option add *Tabnotebook.disabledForeground #a3a3a3 widgetDefault
+option add *Tabnotebook.scrollCommand {} widgetDefault
+option add *Tabnotebook.equalTabs true widgetDefault
+option add *Tabnotebook.font \
+ -Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-* widgetDefault
+option add *Tabnotebook.width 300 widgetDefault
+option add *Tabnotebook.height 150 widgetDefault
+option add *Tabnotebook.foreground Black widgetDefault
+option add *Tabnotebook.background #d9d9d9 widgetDefault
+option add *Tabnotebook.tabForeground Black widgetDefault
+option add *Tabnotebook.tabBackground #d9d9d9 widgetDefault
+option add *Tabnotebook.backdrop #d9d9d9 widgetDefault
+option add *Tabnotebook.margin 4 widgetDefault
+option add *Tabnotebook.tabBorders true widgetDefault
+option add *Tabnotebook.bevelAmount 0 widgetDefault
+option add *Tabnotebook.raiseSelect false widgetDefault
+option add *Tabnotebook.auto true widgetDefault
+option add *Tabnotebook.start 4 widgetDefault
+option add *Tabnotebook.padX 4 widgetDefault
+option add *Tabnotebook.padY 4 widgetDefault
+option add *Tabnotebook.gap overlap widgetDefault
+option add *Tabnotebook.angle 15 widgetDefault
+option add *Tabnotebook.tabPos s widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Tabnotebook {
+ keep -backdrop -background -borderwidth -cursor -disabledforeground \
+ -font -foreground -tabbackground -tabforeground
+}
+
+# ------------------------------------------------------------------
+# TABNOTEBOOK
+# ------------------------------------------------------------------
+itcl::class iwidgets::Tabnotebook {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -borderwidth borderWidth BorderWidth 2
+ itk_option define -state state State normal
+ itk_option define \
+ -disabledforeground disabledForeground DisabledForeground #a3a3a3
+ itk_option define -scrollcommand scrollCommand ScrollCommand {}
+ itk_option define -equaltabs equalTabs EqualTabs true
+ itk_option define -font font Font \
+ -Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*
+ itk_option define -width width Width 300
+ itk_option define -height height Height 150
+ itk_option define -foreground foreground Foreground Black
+ itk_option define -background background Background #d9d9d9
+ itk_option define -tabforeground tabForeground TabForeground Black
+ itk_option define -tabbackground tabBackground TabBackground #d9d9d9
+ itk_option define -backdrop backdrop Backdrop #d9d9d9
+ itk_option define -margin margin Margin 4
+ itk_option define -tabborders tabBorders TabBorders true
+ itk_option define -bevelamount bevelAmount BevelAmount 0
+ itk_option define -raiseselect raiseSelect RaiseSelect false
+ itk_option define -auto auto Auto true
+ itk_option define -start start Start 4
+ itk_option define -padx padX PadX 4
+ itk_option define -pady padY PadY 4
+ itk_option define -gap gap Gap overlap
+ itk_option define -angle angle Angle 15
+ itk_option define -tabpos tabPos TabPos s
+
+ public method add { args }
+ public method configure { args }
+ public method childsite { args }
+ public method delete { args }
+ public method index { args }
+ public method insert { index args }
+ public method prev { }
+ public method next { }
+ public method pageconfigure { index args }
+ public method select { index }
+ public method view { args }
+
+ protected method _reconfigureTabset { }
+ protected method _canvasReconfigure { wid hgt }
+ protected method _pageReconfigure { pageName page wid hgt }
+
+ private method _getArgs { optList args }
+ private method _redrawBorder { wid hgt }
+ private method _recomputeBorder { }
+ private method _pack { tabPos }
+ private method _resize {newWidth_ newHeight_}
+
+ private variable _canvasWidth 0 ;# currently tabnote canvas width
+ private variable _canvasHeight 0 ;# currently tabnote canvas height
+ private variable _nbOptList {} ;# list of notebook options available
+ private variable _tsOptList {} ;# list of tabset options available
+
+ private variable _tabPos s ;# holds -tabPos, because of ordering
+
+ private variable _borderRecompute false ;# did we dirty border after cfg?
+ private variable _tabsetReconfigure false ;# did we dirty tabsets after cfg?
+
+}
+
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::constructor {args} {
+ # The following conditional added for SF ticket #514222. csmith 9/5/02
+ if {$::tk_version > 8.3} {
+ component hull configure -borderwidth 0 -padx 0 -pady 0
+ } else {
+ component hull configure -borderwidth 0
+ }
+
+ #
+ # Create the outermost canvas to maintain geometry.
+ #
+ itk_component add canvas {
+ canvas $itk_interior.canvas -highlightthickness 0
+ } {
+ keep -cursor -background -width -height
+ }
+ bind $itk_component(canvas) <Configure> [itcl::code $this _resize %w %h]
+
+
+
+ # .......................
+ # Create the NOTEBOOK
+ #
+ itk_component add notebook {
+ iwidgets::Notebook $itk_interior.canvas.notebook
+ } {
+ keep -cursor -background
+ }
+
+ #
+ # Ouch, create a dummy page, go pageconfigure to get its options
+ # and munge them into a list for later doling by pageconfigure
+ #
+ $itk_component(notebook) add
+ set nbConfigList [$itk_component(notebook) pageconfigure 0]
+ foreach config $nbConfigList {
+ lappend _nbOptList [lindex $config 0]
+ }
+ $itk_component(notebook) delete 0
+
+ #
+ # Create the tabset.
+ #
+ itk_component add tabset {
+ iwidgets::Tabset $itk_interior.canvas.tabset \
+ -command [itcl::code $this component notebook select]
+ } {
+ keep -cursor
+ }
+
+ eval itk_initialize $args
+
+ #
+ # Ouch, create a dummy tab, go tabconfigure to get its options
+ # and munge them into a list for later doling by pageconfigure
+ #
+ $itk_component(tabset) add
+ set tsConfigList [$itk_component(tabset) tabconfigure 0]
+ foreach config $tsConfigList {
+ lappend _tsOptList [lindex $config 0]
+ }
+ $itk_component(tabset) delete 0
+
+ bind $itk_component(tabset) <Configure> \
+ [itcl::code $this _reconfigureTabset]
+
+ _pack $_tabPos
+ $itk_component(hull) configure -width [cget -width] -height [cget -height]
+}
+
+proc ::iwidgets::tabnotebook {pathName args} {
+ uplevel ::iwidgets::Tabnotebook $pathName $args
+}
+
+
+# -------------------------------------------------------------
+# DESTRUCTOR: destroy the Tabnotebook
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::destructor {} {
+}
+
+# ----------------------------------------------------------------------
+# OPTION -borderwidth
+#
+# Thickness of Notebook Border
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::borderwidth {
+ if {$itk_option(-borderwidth) != {}} {
+ #_recomputeBorder
+ set _borderRecompute true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -state
+#
+# State of the tabs in the tab notebook: normal or disabled
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::state {
+ if {$itk_option(-state) != {}} {
+ $itk_component(tabset) configure -state $itk_option(-state)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -disabledforeground
+#
+# Specifies a foreground color to use for displaying a
+# tab's label when its state is disabled.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::disabledforeground {
+
+ if {$itk_option(-disabledforeground) != {}} {
+ $itk_component(tabset) configure \
+ -disabledforeground $itk_option(-disabledforeground)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -scrollcommand
+#
+# Standard option. See options man pages.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::scrollcommand {
+
+ if {$itk_option(-scrollcommand) != {}} {
+ $itk_component(notebook) \
+ configure -scrollcommand $itk_option(-scrollcommand)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -equaltabs
+#
+# Specifies whether to force tabs to be equal sized or not.
+# A value of true means constrain tabs to be equal sized.
+# A value of false allows each tab to size based on the text
+# label size. The value may have any of the forms accepted by
+# the Tcl_GetBoolean, such as true, false, 0, 1, yes, or no.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::equaltabs {
+
+ if {$itk_option(-equaltabs) != {}} {
+ $itk_component(tabset) \
+ configure -equaltabs $itk_option(-equaltabs)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -font
+#
+# Font for tab labels when they are set to text (-label set)
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::font {
+
+ if {$itk_option(-font) != {}} {
+ $itk_component(tabset) configure -font $itk_option(-font)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -width
+#
+# Width of the Tabnotebook
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::width {
+ if {$itk_option(-width) != {}} {
+ $itk_component(canvas) configure -width $itk_option(-width)
+ #_recomputeBorder
+ set _borderRecompute true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -height
+#
+# Height of the Tabnotebook
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::height {
+ if {$itk_option(-height) != {}} {
+ $itk_component(canvas) configure -height $itk_option(-height)
+ #_recomputeBorder
+ set _borderRecompute true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -foreground
+#
+# Specifies a foreground color to use for displaying a page
+# and its associated tab label (this is the selected state).
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::foreground {
+
+ if {$itk_option(-foreground) != {}} {
+ $itk_component(tabset) configure \
+ -selectforeground $itk_option(-foreground)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -background
+#
+# Specifies a background color to use for displaying a page
+# and its associated tab bg (this is the selected state).
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::background {
+
+ if {$itk_option(-background) != {}} {
+ $itk_component(tabset) configure \
+ -selectbackground $itk_option(-background)
+ #_recomputeBorder
+ set _borderRecompute true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -tabforeground
+#
+# Specifies a foreground color to use for displaying tab labels
+# when they are in their unselected state.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::tabforeground {
+
+ if {$itk_option(-tabforeground) != {}} {
+ $itk_component(tabset) configure \
+ -foreground $itk_option(-tabforeground)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -tabbackground
+#
+# Specifies a background color to use for displaying tab backgrounds
+# when they are in their unselected state.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::tabbackground {
+
+ if {$itk_option(-tabbackground) != {}} {
+ $itk_component(tabset) configure \
+ -background $itk_option(-tabbackground)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -backdrop
+#
+# Specifies a background color to use when filling in the
+# area behind the tabs.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::backdrop {
+
+ if {$itk_option(-backdrop) != {}} {
+ $itk_component(tabset) configure \
+ -backdrop $itk_option(-backdrop)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -margin
+#
+# Sets the backdrop margin between tab edge and backdrop edge
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::margin {
+ if {$itk_option(-margin) != {}} {
+ $itk_component(tabset) configure -margin $itk_option(-margin)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -tabborders
+#
+# Boolean that specifies whether to draw the borders of
+# the unselected tabs (tabs in background)
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::tabborders {
+ if {$itk_option(-tabborders) != {}} {
+ $itk_component(tabset) \
+ configure -tabborders $itk_option(-tabborders)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -bevelamount
+#
+# Specifies pixel size of tab corners. 0 means no corners.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::bevelamount {
+ if {$itk_option(-bevelamount) != {}} {
+ $itk_component(tabset) \
+ configure -bevelamount $itk_option(-bevelamount)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -raiseselect
+#
+# Sets whether to raise selected tabs
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::raiseselect {
+ if {$itk_option(-raiseselect) != {}} {
+ $itk_component(tabset) \
+ configure -raiseselect $itk_option(-raiseselect)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -auto
+#
+# Determines whether pages are automatically unpacked and
+# packed when pages get selected.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::auto {
+ if {$itk_option(-auto) != {}} {
+ $itk_component(notebook) configure -auto $itk_option(-auto)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -start
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::start {
+
+ if {$itk_option(-start) != {}} {
+ $itk_component(tabset) configure \
+ -start $itk_option(-start)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -padx
+#
+# Specifies a non-negative value indicating how much extra space
+# to request for a tab around its label in the X-direction.
+# When computing how large a window it needs, the tab will add
+# this amount to the width it would normally need The tab will
+# end up with extra internal space to the left and right of its
+# text label. This value may have any of the forms acceptable
+# to Tk_GetPixels.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::padx {
+
+ if {$itk_option(-padx) != {}} {
+ $itk_component(tabset) configure -padx $itk_option(-padx)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -pady
+#
+# Specifies a non-negative value indicating how much extra space to
+# request for a tab around its label in the Y-direction. When computing
+# how large a window it needs, the tab will add this amount to the
+# height it would normally need The tab will end up with extra internal
+# space to the top and bot tom of its text label. This value may have
+# any of the forms acceptable to Tk_GetPixels.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::pady {
+
+ if {$itk_option(-pady) != {}} {
+ $itk_component(tabset) configure -pady $itk_option(-pady)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -gap
+#
+# Specifies the amount of pixel space to place between each tab.
+# Value may be any pixel offset value. In addition, a special keyword
+# 'overlap' can be used as the value to achieve a standard overlap of
+# tabs. This value may have any of the forms acceptable to Tk_GetPixels.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::gap {
+
+ if {$itk_option(-gap) != {}} {
+ $itk_component(tabset) configure -gap $itk_option(-gap)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -angle
+#
+# Specifes the angle of slope from the inner edge to the outer edge
+# of the tab. An angle of 0 specifies square tabs. Valid ranges are
+# 0 to 45 degrees inclusive. Default is 15 degrees. If tabPos is
+# e or w, this option is ignored.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::angle {
+
+ if {$itk_option(-angle) != {}} {
+ $itk_component(tabset) configure -angle $itk_option(-angle)
+ #_reconfigureTabset
+ set _tabsetReconfigure true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -tabpos
+#
+# Specifies the location of the set of tabs in relation to the
+# Notebook area. Must be n, s, e, or w. Defaults to s.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabnotebook::tabpos {
+
+ if {$itk_option(-tabpos) != {}} {
+ set _tabPos $itk_option(-tabpos)
+ $itk_component(tabset) configure \
+ -tabpos $itk_option(-tabpos)
+ pack forget $itk_component(canvas)
+ pack forget $itk_component(tabset)
+ pack forget $itk_component(notebook)
+ _pack $_tabPos
+ }
+}
+
+# -------------------------------------------------------------
+# METHOD: configure ?<option>? ?<value> <option> <value>...?
+#
+# Acts as an addendum to the itk::Widget::configure method.
+#
+# Checks the _recomputeBorder flag and the _tabsetReconfigure to
+# determine what work has been batched to after the configure
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::configure { args } {
+ set result [eval itk::Archetype::configure $args]
+
+ # check for flags then do update...
+ if { $_borderRecompute == "true" } {
+ _recomputeBorder
+ set _borderRecompute false
+ }
+
+ if { $_tabsetReconfigure == "true" } {
+ _reconfigureTabset
+ set _tabsetReconfigure false
+ }
+
+ return $result
+
+}
+
+# -------------------------------------------------------------
+# METHOD: add ?<option> <value>...?
+#
+# Creates a page and appends it to the list of pages.
+# processes pageconfigure for the page added.
+#
+# Returns the page's childsite frame
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::add { args } {
+
+ # The args list should be an even # of params, if not then
+ # prob missing value for last item in args list. Signal error.
+ set len [llength $args]
+ if { [expr {$len % 2}] } {
+ error "value for \"[lindex $args [expr {$len - 1}]]\" missing"
+ }
+
+ # pick out the notebook args
+ set nbArgs [eval _getArgs [list $_nbOptList] $args]
+ set pageName [eval $itk_component(notebook) add $nbArgs]
+
+ # pick out the tabset args
+ set tsArgs [eval _getArgs [list $_tsOptList] $args]
+ eval $itk_component(tabset) add $tsArgs
+
+ set page [index end]
+ bind $pageName <Configure> \
+ [itcl::code $this _pageReconfigure $pageName $page %w %h]
+ return $pageName
+}
+
+# -------------------------------------------------------------
+# METHOD: childsite ?<index>?
+#
+# If index is supplied, returns the child site widget
+# corresponding to the page index. If called with no arguments,
+# returns a list of all child sites
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::childsite { args } {
+ return [eval $itk_component(notebook) childsite $args]
+}
+
+# -------------------------------------------------------------
+# METHOD: delete <index1> ?<index2>?
+#
+# Deletes a page or range of pages from the notebook
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::delete { args } {
+ eval $itk_component(notebook) delete $args
+ eval $itk_component(tabset) delete $args
+}
+
+
+# -------------------------------------------------------------
+# METHOD: index <index>
+#
+# Given an index identifier returns the numeric index of the page
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::index { args } {
+ return [eval $itk_component(notebook) index $args]
+}
+
+# -------------------------------------------------------------
+# METHOD: insert <index> ?<option> <value>...?
+#
+# Inserts a page before a index. The before page may
+# be specified as a label or a page position.
+#
+# Note that since we use eval to preserve the $args list,
+# we must use list around $index to keep it together as a unit
+#
+# Returns the name of the page's child site
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::insert { index args } {
+
+ # pick out the notebook args
+ set nbArgs [eval _getArgs [list $_nbOptList] $args]
+ set pageName [eval $itk_component(notebook) insert [list $index] $nbArgs]
+
+ # pick out the tabset args
+ set tsArgs [eval _getArgs [list $_tsOptList] $args]
+ eval $itk_component(tabset) insert [list $index] $tsArgs
+
+ return $pageName
+
+}
+
+# -------------------------------------------------------------
+# METHOD: prev
+#
+# Selects the previous page. Wraps at first back to last page.
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::prev { } {
+ eval $itk_component(notebook) prev
+ eval $itk_component(tabset) prev
+}
+
+# -------------------------------------------------------------
+# METHOD: next
+#
+# Selects the next page. Wraps at last back to first page.
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::next { } {
+ eval $itk_component(notebook) next
+ eval $itk_component(tabset) next
+}
+
+# -------------------------------------------------------------
+# METHOD: pageconfigure <index> ?<option> <value>...?
+#
+# Performs configure on a given page denoted by index.
+# Index may be a page number or a pattern matching the label
+# associated with a page.
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::pageconfigure { index args } {
+
+ set nbArgs [eval _getArgs [list $_nbOptList] $args]
+ set tsArgs [eval _getArgs [list $_tsOptList] $args]
+
+ set len [llength $args]
+ switch $len {
+ 0 {
+ # Here is the case where they just want to query options
+ set nbConfig \
+ [eval $itk_component(notebook) pageconfigure $index $nbArgs]
+ set tsConfig \
+ [eval $itk_component(tabset) tabconfigure $index $tsArgs]
+ #
+ # BUG: this currently just concatenates a page and a tab's
+ # config lists together... We should bias to the Page
+ # since this is what we are using as primary when both??
+ #
+ # a pageconfigure index -background will return something like:
+ # -background background Background #9D008FF583C1 gray70 \
+ # -background background background white gray 70
+ #
+ return [concat $nbConfig $tsConfig]
+ }
+ 1 {
+ # Here is the case where they are asking for only one
+ # one options value... need to figure out which one
+ # (page or tab) can service this. Then only return
+ # that one's result.
+
+ if { [llength $nbArgs] != 0 } {
+ return [eval $itk_component(notebook) \
+ pageconfigure $index $nbArgs]
+ } elseif { [llength $tsArgs] != 0 } {
+ return [eval $itk_component(tabset) \
+ tabconfigure $index $tsArgs]
+ } else {
+ error "unknown option \"$args\""
+ }
+
+ }
+ default {
+
+ # pick out the notebook args
+ set nbConfig \
+ [eval $itk_component(notebook) \
+ pageconfigure [list $index] $nbArgs]
+
+ # pick out the tabset args
+ set tsConfig \
+ [eval $itk_component(tabset) \
+ tabconfigure [list $index] $tsArgs]
+
+ return ""
+ #return [concat $nbConfig $tsConfig]
+
+ }
+ }
+}
+
+# -------------------------------------------------------------
+# METHOD: select index
+#
+# Select a page by index
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::select { index } {
+ $itk_component(notebook) select $index
+ $itk_component(tabset) select $index
+}
+
+# -------------------------------------------------------------
+# METHOD: view
+#
+# Return the current page
+#
+# view index
+#
+# Selects the page denoted by index to be current page
+#
+# view 'moveto' fraction
+#
+# Selects the page by using fraction amount
+#
+# view 'scroll' num what
+#
+# Selects the page by using num as indicator of next or
+# previous
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::view { args } {
+ eval $itk_component(notebook) view $args
+ $itk_component(tabset) select [index select]
+}
+
+# -------------------------------------------------------------
+# PRIVATE METHOD: _getArgs
+#
+# Given an optList returned from a configure on an object and
+# given a candidate argument list, peruse throught the optList
+# and build a new argument list with only those options found
+# in optList.
+#
+# This is used by the add, insert, and pageconfigure methods.
+# It is useful for a container kind of class like Tabnotebook
+# to be smart about args it gets for its concept of a "page"
+# which is actually a Notebook Page and a Tabset Tab.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::_getArgs { optList args } {
+
+ set len [llength $args]
+
+ set retArgs {}
+
+ for {set i 0} {$i < $len} {incr i} {
+ # get the option for this pair
+ set opt [lindex $args $i]
+
+ # move ahead to the value
+ incr i
+
+ # option exists!
+ if { [lsearch -exact $optList $opt] != -1} {
+ lappend retArgs $opt
+ if {$i < [llength $args]} {
+ lappend retArgs [lindex $args $i]
+ }
+ # option does not exist
+ }
+ }
+
+ return $retArgs
+}
+
+# -------------------------------------------------------------
+# PROTECTED METHOD: _reconfigureTabset
+#
+# bound to the tabset reconfigure... We call our canvas
+# reconfigure as if the canvas resized, it then configures
+# the tabset correctly.
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::_reconfigureTabset { } {
+ _canvasReconfigure $_canvasWidth $_canvasHeight
+
+}
+
+# -------------------------------------------------------------
+# PROTECTED METHOD: _canvasReconfigure
+#
+# bound to window Reconfigure event of the canvas
+# keeps the tabset area stretched in its major dimension.
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::_canvasReconfigure { wid hgt } {
+
+ if { $_tabPos == "n" || $_tabPos == "s" } {
+ $itk_component(tabset) configure -width $wid
+ } else {
+ $itk_component(tabset) configure -height $hgt
+ }
+
+ set _canvasWidth $wid
+ set _canvasHeight $hgt
+
+ _redrawBorder $wid $hgt
+
+}
+
+# -------------------------------------------------------------
+# PRIVATE METHOD: _redrawBorder
+#
+# called by methods when the packing changes, borderwidths, etc.
+# and height
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::_redrawBorder { wid hgt } {
+
+ # Get the top of the Notebook area...
+
+ set nbTop [winfo y $itk_component(notebook)]
+ set canTop [expr {$nbTop - $itk_option(-borderwidth)}]
+
+ $itk_component(canvas) delete BORDER
+ if { $itk_option(-borderwidth) > 0 } {
+
+ # For south, east, and west -- draw the top/north edge
+ if { $_tabPos != "n" } {
+ $itk_component(canvas) create line \
+ [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
+ [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
+ $wid \
+ [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
+ -width $itk_option(-borderwidth) \
+ -fill [iwidgets::colors::topShadow $itk_option(-background)] \
+ -tags BORDER
+ }
+
+ # For north, east, and west -- draw the bottom/south edge
+ if { $_tabPos != "s" } {
+ $itk_component(canvas) create line \
+ [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
+ [expr {floor($hgt - ($itk_option(-borderwidth)/2.0))}] \
+ [expr {floor($wid - ($itk_option(-borderwidth)/2.0))}] \
+ [expr {floor($hgt - ($itk_option(-borderwidth)/2.0))}] \
+ -width $itk_option(-borderwidth) \
+ -fill [iwidgets::colors::bottomShadow $itk_option(-background)] \
+ -tags BORDER
+ }
+
+ # For north, south, and east -- draw the left/west edge
+ if { $_tabPos != "w" } {
+ $itk_component(canvas) create line \
+ [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
+ 0 \
+ [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
+ $hgt \
+ -width $itk_option(-borderwidth) \
+ -fill [iwidgets::colors::topShadow $itk_option(-background)] \
+ -tags BORDER
+ }
+
+ # For north, south, and west -- draw the right/east edge
+ if { $_tabPos != "e" } {
+ $itk_component(canvas) create line \
+ [expr {floor($wid - ($itk_option(-borderwidth)/2.0))}] \
+ [expr {floor(0 + ($itk_option(-borderwidth)/2.0))}] \
+ [expr {floor($wid - ($itk_option(-borderwidth)/2.0))}] \
+ $hgt \
+ -width $itk_option(-borderwidth) \
+ -fill [iwidgets::colors::bottomShadow $itk_option(-background)] \
+ -tags BORDER
+ }
+ }
+
+}
+
+# -------------------------------------------------------------
+# PRIVATE METHOD: _recomputeBorder
+#
+# Based on current width and height of our canvas, repacks
+# the notebook with padding for borderwidth, and calls
+# redraw border method
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::_recomputeBorder { } {
+
+ set wid [winfo width $itk_component(canvas)]
+ set hgt [winfo height $itk_component(canvas)]
+
+ _pack $_tabPos
+ _redrawBorder $wid $hgt
+}
+
+# -------------------------------------------------------------
+# PROTECTED METHOD: _pageReconfigure
+#
+# This method will eventually reconfigure the tab notebook's
+# notebook area to contain the resized child site
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::_pageReconfigure { pageName page wid hgt } {
+}
+
+# -------------------------------------------------------------
+# PRIVATE METHOD: _pack
+#
+# This method packs the notebook and tabset correctly according
+# to the current $tabPos
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::_pack { tabPos } {
+
+ pack $itk_component(canvas) -fill both -expand yes
+ pack propagate $itk_component(canvas) no
+
+ switch $tabPos {
+ n {
+ # north
+ pack $itk_component(tabset) \
+ -anchor nw \
+ -fill x \
+ -expand no
+ pack $itk_component(notebook) \
+ -fill both \
+ -expand yes \
+ -padx $itk_option(-borderwidth) \
+ -pady $itk_option(-borderwidth) \
+ -side bottom
+ }
+ s {
+ # south
+ pack $itk_component(notebook) \
+ -anchor nw \
+ -fill both \
+ -expand yes \
+ -padx $itk_option(-borderwidth) \
+ -pady $itk_option(-borderwidth)
+
+ pack $itk_component(tabset) \
+ -side left \
+ -fill x \
+ -expand yes
+ }
+ w {
+ # west
+ pack $itk_component(tabset) \
+ -anchor nw \
+ -side left \
+ -fill y \
+ -expand no
+ pack $itk_component(notebook) \
+ -anchor nw \
+ -side left \
+ -fill both \
+ -expand yes \
+ -padx $itk_option(-borderwidth) \
+ -pady $itk_option(-borderwidth)
+
+ }
+ e {
+ # east
+ pack $itk_component(notebook) \
+ -side left \
+ -anchor nw \
+ -fill both \
+ -expand yes \
+ -padx $itk_option(-borderwidth) \
+ -pady $itk_option(-borderwidth)
+
+ pack $itk_component(tabset) \
+ -fill y \
+ -expand yes
+ }
+ }
+
+ set wid [winfo width $itk_component(canvas)]
+ set hgt [winfo height $itk_component(canvas)]
+
+ _redrawBorder $wid $hgt
+}
+
+
+
+# -------------------------------------------------------------
+# PRIVATE METHOD: _resize
+#
+# This method added by csmith, 5/1/01, to fix a bug with the
+# geometry of the tabnotebook. The hull component's geometry
+# was not being updated properly on <Configure> events.
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabnotebook::_resize {newWidth_ newHeight_} {
+ _canvasReconfigure $newWidth_ $newHeight_
+
+ # csmith: 9/14/01 - Commenting out the following code due to
+ # SF ticket 461471, which is a dup of the original 452803. Since I
+ # can't remember the exact problem surrounding the need to add
+ # the _resize method, I'm going to do an undo here, leaving the
+ # code for future reference if needed. Should the original problem
+ # arise again I will reinvestigate the need for _resize.
+ #
+ # after idle \
+ # "$this component hull configure -width $newWidth_ -height $newHeight_"
+}
diff --git a/iwidgets/generic/tabset.itk b/iwidgets/generic/tabset.itk
new file mode 100644
index 00000000000..99c22fb0e28
--- /dev/null
+++ b/iwidgets/generic/tabset.itk
@@ -0,0 +1,2753 @@
+#
+# Tabset Widget and the Tab Class
+# ----------------------------------------------------------------------
+# A Tabset is a widget that contains a set of Tab buttons.
+# It displays these tabs in a row or column depending on it tabpos.
+# When a tab is clicked on, it becomes the only tab in the tab set that
+# is selected. All other tabs are deselected. The Tcl command prefix
+# associated with this tab (through the command tab configure option)
+# is invoked with the tab index number appended to its argument list.
+# This allows the Tabset to control another widget such as a Notebook.
+#
+# A Tab class is an [incr Tcl] class that displays either an image,
+# bitmap, or label in a graphic object on a canvas. This graphic object
+# can have a wide variety of appearances depending on the options set.
+#
+# WISH LIST:
+# This section lists possible future enhancements.
+#
+# 1) When too many tabs appear, a small scrollbar should appear to
+# move the tabs over.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Bill W. Scott EMAIL: bscott@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Tabset.width 0 widgetDefault
+option add *Tabset.height 0 widgetDefault
+option add *Tabset.equalTabs true widgetDefault
+option add *Tabset.tabPos s widgetDefault
+option add *Tabset.raiseSelect false widgetDefault
+option add *Tabset.start 4 widgetDefault
+option add *Tabset.margin 5 widgetDefault
+option add *Tabset.tabBorders true widgetDefault
+option add *Tabset.bevelAmount 0 widgetDefault
+option add *Tabset.padX 4 widgetDefault
+option add *Tabset.padY 4 widgetDefault
+option add *Tabset.gap overlap widgetDefault
+option add *Tabset.angle 20 widgetDefault
+option add *Tabset.font fixed widgetDefault
+option add *Tabset.state normal widgetDefault
+option add *Tabset.disabledForeground #a3a3a3 widgetDefault
+option add *Tabset.foreground black widgetDefault
+option add *Tabset.background #d9d9d9 widgetDefault
+option add *Tabset.selectForeground black widgetDefault
+option add *Tabset.selectBackground #ececec widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Tabset {
+ keep -backdrop -background -cursor -disabledforeground -font -foreground \
+ -selectbackground -selectforeground
+}
+
+# ------------------------------------------------------------------
+# TABSET
+# ------------------------------------------------------------------
+itcl::class iwidgets::Tabset {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -width width Width 0
+ itk_option define -equaltabs equalTabs EqualTabs true
+ itk_option define -height height Height 0
+ itk_option define -tabpos tabPos TabPos s
+ itk_option define -raiseselect raiseSelect RaiseSelect false
+ itk_option define -start start Start 4
+ itk_option define -margin margin Margin 5
+ itk_option define -tabborders tabBorders TabBorders true
+ itk_option define -bevelamount bevelAmount BevelAmount 0
+ itk_option define -padx padX PadX 4
+ itk_option define -pady padY PadY 4
+ itk_option define -gap gap Gap overlap
+ itk_option define -angle angle Angle 20
+ itk_option define -font font Font fixed
+ itk_option define -state state State normal
+ itk_option define \
+ -disabledforeground disabledForeground DisabledForeground #a3a3a3
+ itk_option define -foreground foreground Foreground black
+ itk_option define -background background Background #d9d9d9
+ itk_option define -selectforeground selectForeground Background black
+ itk_option define -backdrop backdrop Backdrop white
+ itk_option define -selectbackground selectBackground Foreground #ececec
+ itk_option define -command command Command {}
+
+ public method configure {args}
+ public method add {args}
+ public method delete {args}
+ public method index {index}
+ public method insert {index args}
+ public method prev {}
+ public method next {}
+ public method select {index}
+ public method tabcget {index args}
+ public method tabconfigure {index args}
+ public method bbox {}
+
+ protected method _selectName {tabName}
+
+ private method _createTab {args}
+ private method _deleteTabs {fromTab toTab}
+ private method _index {pathList index select}
+ private method _tabConfigure {args}
+ private method _relayoutTabs {}
+ private method _drawBevelBorder {}
+ private method _calcNextTabOffset {tabName}
+ private method _tabBounds {}
+ private method _recalcCanvasGeom {}
+ private method _canvasReconfigure {width height}
+ private method _startMove {x y}
+ private method _moveTabs {x y}
+ private method _endMove {x y}
+ private method _configRelayout {}
+
+ private variable _width 0 ;# Width of the canvas in screen units
+ private variable _height 0 ;# Height of the canvas in screen units
+ private variable _selectedTop 0 ;# top edge of tab + a margin
+ private variable _deselectedTop 0 ;# top edge of tab + a margin&raiseamt
+ private variable _selectedLeft 0 ;# left edge of tab + a margin
+ private variable _deselectedLeft 0 ;# left edge of tab + a margin&raiseamt
+ private variable _tabs {} ;# our internal list of tabs
+ private variable _currTab -1 ;# numerical index # of selected tab
+ private variable _uniqueID 0 ;# used to create unique names
+ private variable _cmdStr {} ;# holds value of itk_option(-command)
+ ;# do not know why I need this!
+ private variable _canvasWidth 0 ;# set by canvasReconfigure, is can wid
+ private variable _canvasHeight 0 ;# set by canvasReconfigure, is can hgt
+
+ private variable _anchorX 0 ;# used by mouse scrolling methods
+ private variable _anchorY 0 ;# used by mouse scrolling methods
+
+ private variable _margin 0 ;# -margin in screen units
+ private variable _start 0 ;# -start in screen units
+ private variable _gap overlap ;# -gap in screen units
+
+ private variable _relayout false ;# flag tripped to tell whether to
+ ;# relayout tabs after the configure
+ private variable _skipRelayout false ;# flag that tells whether to skip
+ ;# relayouting out the tabs. used by
+ ;# _endMove.
+}
+
+#
+# Provide a lowercase access method for the Tabset class
+#
+proc ::iwidgets::tabset {pathName args} {
+ uplevel ::iwidgets::Tabset $pathName $args
+}
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::constructor {args} {
+ global tcl_platform
+
+ #
+ # Create the canvas that holds the tabs
+ #
+ itk_component add canvas {
+ canvas $itk_interior.canvas -highlightthickness 0
+ } {
+ keep -cursor -width -height
+ }
+ pack $itk_component(canvas) -fill both -expand yes -anchor nw
+
+ # ... This gives us a chance to redraw our bevel borders, etc when
+ # the size of our canvas changes...
+ bind $itk_component(canvas) <Configure> \
+ [itcl::code $this _canvasReconfigure %w %h]
+ bind $itk_component(canvas) <Map> \
+ [itcl::code $this _relayoutTabs]
+
+
+ # ... Allow button 2 scrolling as in label widget.
+ if {$tcl_platform(os) != "HP-UX"} {
+ bind $itk_component(canvas) <2> \
+ [itcl::code $this _startMove %x %y]
+ bind $itk_component(canvas) <B2-Motion> \
+ [itcl::code $this _moveTabs %x %y]
+ bind $itk_component(canvas) <ButtonRelease-2> \
+ [itcl::code $this _endMove %x %y]
+ }
+
+ # @@@
+ # @@@ Is there a better way?
+ # @@@
+
+ bind $itk_component(hull) <Tab> [itcl::code $this next]
+ bind $itk_component(hull) <Shift-Tab> [itcl::code $this prev]
+
+ eval itk_initialize $args
+
+ _configRelayout
+
+ _recalcCanvasGeom
+
+}
+
+itcl::body iwidgets::Tabset::destructor {} {
+ foreach tab $_tabs {
+ itcl::delete object $tab
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTIONS
+# ----------------------------------------------------------------------
+
+# ----------------------------------------------------------------------
+# OPTION -width
+#
+# Sets the width explicitly for the canvas of the tabset
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::width {
+ if {$itk_option(-width) != {}} {
+ }
+ set _width [winfo pixels $itk_interior $itk_option(-width)]
+}
+
+# ----------------------------------------------------------------------
+# OPTION -equaltabs
+#
+# If set to true, causes horizontal tabs to be equal in
+# in width and vertical tabs to equal in height.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::equaltabs {
+ if {$itk_option(-equaltabs) != {}} {
+ set _relayout true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -height
+#
+# Sets the height explicitly for the canvas of the tabset
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::height {
+ set _height [winfo pixels $itk_interior $itk_option(-height)]
+}
+
+# ----------------------------------------------------------------------
+# OPTION -tabpos
+#
+# Sets the tab position of tabs, n, s, e, w
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::tabpos {
+ if {$itk_option(-tabpos) != {}} {
+ switch $itk_option(-tabpos) {
+ n {
+ _tabConfigure -invert true -orient horizontal
+ }
+ s {
+ _tabConfigure -invert false -orient horizontal
+ }
+ w {
+ _tabConfigure -invert false -orient vertical
+ }
+ e {
+ _tabConfigure -invert true -orient vertical
+ }
+ default {
+ error "bad anchor position\
+ \"$itk_option(-tabpos)\" must be n, s, e, or w"
+ }
+ }
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -raiseselect
+#
+# Sets whether to raise selected tabs slightly
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::raiseselect {
+ if {$itk_option(-raiseselect) != {}} {
+ set _relayout true
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -start
+#
+# Sets the offset to start of tab set
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::start {
+ if {$itk_option(-start) != {}} {
+ set _start [winfo pixels $itk_interior $itk_option(-start)]
+ set _relayout true
+ } else {
+ set _start 4
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -margin
+#
+# Sets the margin used above n tabs, below s tabs, left of e
+# tabs, right of w tabs
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::margin {
+ if {$itk_option(-margin) != {}} {
+ set _margin [winfo pixels $itk_interior $itk_option(-margin)]
+ set _relayout true
+ } else {
+ set _margin 5
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -tabborders
+#
+# Boolean that specifies whether to draw the borders of
+# the unselected tabs (tabs in background)
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::tabborders {
+ if {$itk_option(-tabborders) != {}} {
+ _tabConfigure -tabborders $itk_option(-tabborders)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -bevelamount
+#
+# Specifies pixel size of tab corners. 0 means no corners.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::bevelamount {
+ if {$itk_option(-bevelamount) != {}} {
+ _tabConfigure -bevelamount $itk_option(-bevelamount)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -padx
+#
+# Sets the padding in each tab to the left and right of label
+# I don't convert for fpixels, since Tab does it for me.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::padx {
+ if {$itk_option(-padx) != {}} {
+ _tabConfigure -padx $itk_option(-padx)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -pady
+#
+# Sets the padding in each tab to the left and right of label
+# I don't convert for fpixels, since Tab does it for me.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::pady {
+ if {$itk_option(-pady) != {}} {
+ _tabConfigure -pady $itk_option(-pady)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -gap
+#
+# Sets the amount of spacing between tabs in pixels
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::gap {
+ if {$itk_option(-gap) != {}} {
+ if {$itk_option(-gap) != "overlap"} {
+ set _gap [winfo pixels $itk_interior $itk_option(-gap)]
+ } else {
+ set _gap overlap
+ }
+ set _relayout true
+ } else {
+ set _gap overlap
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -angle
+#
+# Sets the angle of the tab's sides
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::angle {
+ if {$itk_option(-angle) != {}} {
+ _tabConfigure -angle $itk_option(-angle)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -font
+#
+# Sets the font of the tab (SELECTED and UNSELECTED)
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::font {
+ if {$itk_option(-font) != {}} {
+ _tabConfigure -font $itk_option(-font)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -state
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::state {
+ if {$itk_option(-state) != {}} {
+ _tabConfigure -state $itk_option(-state)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -disabledforeground
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::disabledforeground {
+ if {$itk_option(-disabledforeground) != {}} {
+ _tabConfigure \
+ -disabledforeground $itk_option(-disabledforeground)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -foreground
+#
+# Sets the foreground label color of UNSELECTED tabs
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::foreground {
+ _tabConfigure -foreground $itk_option(-foreground)
+}
+
+# ----------------------------------------------------------------------
+# OPTION -background
+#
+# Sets the background color of UNSELECTED tabs
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::background {
+ if {$itk_option(-background) != {}} {
+ _tabConfigure -background $itk_option(-background)
+ } else {
+ _tabConfigure -background \
+ [$itk_component(canvas) cget -background]
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -selectforeground
+#
+# Sets the foreground label color of SELECTED tabs
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::selectforeground {
+ _tabConfigure -selectforeground $itk_option(-selectforeground)
+}
+
+# ----------------------------------------------------------------------
+# OPTION -backdrop
+#
+# Sets the background color of the Tabset backdrop (behind the tabs)
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::backdrop {
+ if {$itk_option(-backdrop) != {}} {
+ $itk_component(canvas) configure \
+ -background $itk_option(-backdrop)
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -selectbackground
+#
+# Sets the background color of SELECTED tabs
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::selectbackground {
+ if {$itk_option(-selectbackground) != {}} {
+ } else {
+ #set _selectBackground \
+ [$itk_component(canvas) cget -background]
+ }
+ _tabConfigure -selectbackground $itk_option(-selectbackground)
+}
+
+# ----------------------------------------------------------------------
+# OPTION -command
+#
+# The command to invoke when a tab is hit.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tabset::command {
+ if {$itk_option(-command) != {}} {
+ set _cmdStr $itk_option(-command)
+ }
+}
+
+# ----------------------------------------------------------------------
+# METHOD: add ?option value...?
+#
+# Creates a tab and appends it to the list of tabs.
+# processes tabconfigure for the tab added.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::add {args} {
+ set tabName [eval _createTab $args]
+ lappend _tabs $tabName
+
+ _relayoutTabs
+
+ return $tabName
+}
+
+# ----------------------------------------------------------------------
+# METHOD: configure ?option? ?value option value...?
+#
+# Acts as an addendum to the itk::Widget::configure method.
+#
+# Checks the _relayout flag to see if after configures are done
+# we need to relayout the tabs.
+#
+# _skipRelayout is set in the MB2 scroll methods, to avoid constant
+# relayout of tabs while dragging the mouse.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::configure {args} {
+ set result [eval itk::Archetype::configure $args]
+
+ _configRelayout
+
+ return $result
+}
+
+itcl::body iwidgets::Tabset::_configRelayout {} {
+ # then relayout tabs if necessary
+ if { $_relayout } {
+ if { $_skipRelayout } {
+ } else {
+ _relayoutTabs
+ }
+ set _relayout false
+ }
+}
+
+# ----------------------------------------------------------------------
+# METHOD: delete index1 ?index2?
+#
+# Deletes a tab or range of tabs from the tabset
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::delete {args} {
+ if { $_tabs == {} } {
+ error "can't delete tabs,\
+ no tabs in the tabset named $itk_component(hull)"
+ }
+
+ set len [llength $args]
+ switch $len {
+ 0 {
+ error "wrong # args: should be\
+ \"$itk_component(hull) delete index1 ?index2?\""
+ }
+
+ 1 {
+ set fromTab [index [lindex $args 0]]
+ if { $fromTab == -1 } {
+ error "bad value for index1:\
+ [lindex $args 0] in call to delete"
+ }
+ set toTab $fromTab
+ _deleteTabs $fromTab $toTab
+ }
+
+ 2 {
+ set fromTab [index [lindex $args 0]]
+ if { $fromTab == -1 } {
+ error "bad value for index1:\
+ [lindex $args 0] in call to delete"
+ }
+ set toTab [index [lindex $args 1]]
+
+ if { $toTab == -1 } {
+ error "bad value for index2:\
+ [lindex $args 1] in call to delete"
+ }
+ _deleteTabs $fromTab $toTab
+ }
+
+ default {
+ error "wrong # args: should be\
+ \"$itk_component(hull) delete index1 ?index2?\""
+ }
+ }
+}
+
+# ----------------------------------------------------------------------
+# METHOD: index index
+#
+# Given an index identifier returns the numeric index of the tab
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::index {index} {
+ return [_index $_tabs $index $_currTab]
+}
+
+# ----------------------------------------------------------------------
+# METHOD: insert index ?option value...?
+#
+# Inserts a tab before a index. The before tab may
+# be specified as a label or a tab position.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::insert {index args} {
+ if { $_tabs == {} } {
+ error "no tab to insert before,\
+ tabset '$itk_component(hull)' is empty"
+ }
+
+ # get the tab
+ set tab [index $index]
+
+ # catch bad value for before tab.
+ if { $tab < 0 || $tab >= [llength $_tabs] } {
+ error "bad value $tab for index:\
+ should be between 0 and [expr {[llength $_tabs] - 1}]"
+ }
+
+ # create the new tab and get its name...
+ set tabName [eval _createTab $args]
+
+ # grab the name of the tab currently selected. (to keep in sync)
+ set currTabName [lindex $_tabs $_currTab]
+
+ # insert tabName before $tab
+ set _tabs [linsert $_tabs $tab $tabName]
+
+ # keep the _currTab in sync with the insert.
+ set _currTab [lsearch -exact $_tabs $currTabName]
+
+ _relayoutTabs
+
+ return $tabName
+}
+
+# ----------------------------------------------------------------------
+# METHOD: prev
+#
+# Selects the prev tab. Wraps at first back to last tab.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::prev {} {
+ if { $_tabs == {} } {
+ error "can't goto previous tab,\
+ no tabs in the tabset: $itk_component(hull)"
+ }
+
+ # bump to the previous tab and wrap if necessary
+ set prev [expr {$_currTab - 1}]
+ if { $prev < 0 } {
+ set prev [expr {[llength $_tabs] - 1}]
+ }
+
+ select $prev
+
+}
+
+# ----------------------------------------------------------------------
+# METHOD: next
+#
+# Selects the next tab. Wraps at last back to first tab.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::next {} {
+ if { $_tabs == {} } {
+ error "can't goto next tab,\
+ no tabs in the tabset: $itk_component(hull)"
+ }
+
+ # bump to the next tab and wrap if necessary
+ set next [expr {$_currTab + 1}]
+ if { $next >= [llength $_tabs] } {
+ set next 0
+ }
+
+ select $next
+}
+
+# ----------------------------------------------------------------------
+# METHOD: select index
+#
+# Select a tab by index
+#
+# Lowers the last _currTab if it existed.
+# Then raises the new one if it exists.
+#
+# Returns numeric index of selection, -1 if failed.
+# -------------------------------------------------------------
+itcl::body iwidgets::Tabset::select {index} {
+ if { $_tabs == {} } {
+ error "can't activate a tab,\
+ no tabs in the tabset: $itk_component(hull)"
+ }
+
+ # if there is not current selection just ignore trying this selection
+ if { $index == "select" && $_currTab == -1 } {
+ return -1
+ }
+
+ # is selection request in range ?
+ set reqTab [index $index]
+ if { $reqTab == -1 } {
+ error "bad value $index for index:\
+ should be from 0 to [expr {[llength $_tabs] - 1}]"
+ }
+
+ # If already selected then ignore and return...
+ if { $reqTab == $_currTab } {
+ return $reqTab
+ }
+
+ # ---- Deselect
+ if { $_currTab != -1 } {
+ set currTabName [lindex $_tabs $_currTab]
+ $currTabName deselect
+
+ # handle different orientations...
+ if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s"} {
+ $currTabName configure -top $_deselectedTop
+ } else {
+ $currTabName configure -left $_deselectedLeft
+ }
+ }
+
+ # get the stacking order correct...
+ foreach tab $_tabs {
+ $tab lower
+ }
+
+ # set this now so that the -command cmd can do an 'index select'
+ # to operate on this tab.
+ set _currTab $reqTab
+
+ # ---- Select
+ set reqTabName [lindex $_tabs $reqTab]
+ $reqTabName select
+ if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s"} {
+ $reqTabName configure -top $_selectedTop
+ } else {
+ $reqTabName configure -left $_selectedLeft
+ }
+
+ set _currTab $reqTab
+
+ # invoke any user command string, appended with tab index number
+ if { $_cmdStr != {} } {
+ set newCmd $_cmdStr
+ eval [lappend newCmd $reqTab]
+ }
+
+ return $reqTab
+}
+
+# ----------------------------------------------------------------------
+# METHOD: tabcget index ?option?
+#
+# Returns the value for the option setting of the tab at index $index.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::tabcget {index args} {
+ return [lindex [eval tabconfigure $index $args] 2]
+}
+
+# ----------------------------------------------------------------------
+# METHOD: tabconfigure index ?option? ?value option value?
+#
+# tabconfigure index : returns configuration list
+# tabconfigure index -option : returns option values
+# tabconfigure index ?option value option value ...? sets options
+# and returns empty string.
+#
+# Performs configure on a given tab denoted by index.
+#
+# Index may be a tab number or a pattern matching the label
+# associated with a tab.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::tabconfigure {index args} {
+ # convert index to numeric
+ set tab [index $index]
+
+ if { $tab == -1 } {
+ error "bad index value:\
+ $index for $itk_component(hull) tabconfigure"
+ }
+
+ set tabName [lindex $_tabs $tab]
+
+ set len [llength $args]
+ switch $len {
+ 0 {
+ return [eval $tabName configure]
+ }
+ 1 {
+ return [eval $tabName configure $args]
+ }
+ default {
+ eval $tabName configure $args
+ _relayoutTabs
+ select select
+ }
+ }
+ return ""
+}
+
+# ----------------------------------------------------------------------
+# METHOD: bbox
+#
+# calculates the bounding box that will completely enclose
+# all the tabs.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::bbox {} {
+ return [_tabBounds]
+}
+
+# ----------------------------------------------------------------------
+# PROTECTED METHOD: _selectName
+#
+# internal method to allow selection by internal tab name
+# rather than index. This is used by the bind methods
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_selectName {tabName} {
+ # if the tab is disabled, then ignore this selection...
+ if { [$tabName cget -state] == "disabled" } {
+ return
+ }
+
+ set tab [lsearch -exact $_tabs $tabName]
+ select $tab
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _createTab
+#
+# Creates a tab, using unique tab naming, propagates background
+# and keeps unique id up to date.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_createTab {args} {
+ #
+ # create an internal name for the tab: tab0, tab1, etc.
+ # these are one-up numbers they do not
+ # correspond to the position the tab is located in.
+ #
+ set tabName $this-tab$_uniqueID
+
+ switch $itk_option(-tabpos) {
+ n {
+ set invert true
+ set orient horizontal
+ set x 0
+ set y [expr {$_margin + 1}]
+ }
+ s {
+ set invert false
+ set orient horizontal
+ set x 0
+ set y 0
+ }
+ w {
+ set invert false
+ set orient vertical
+ set x 0
+ set y 0
+ }
+ e {
+ set invert true
+ set orient vertical
+ set x [expr {$_margin + 1}]
+ set y 0
+ }
+ default {
+ error "bad anchor position\
+ \"$itk_option(-tabpos)\" must be n, s, e, or w"
+ }
+ }
+
+ eval iwidgets::Tab $tabName $itk_component(canvas) \
+ -left $x \
+ -top $y \
+ -font [list $itk_option(-font)] \
+ -background $itk_option(-background) \
+ -foreground $itk_option(-foreground) \
+ -selectforeground $itk_option(-selectforeground) \
+ -disabledforeground $itk_option(-disabledforeground) \
+ -selectbackground $itk_option(-selectbackground) \
+ -angle $itk_option(-angle) \
+ -padx $itk_option(-padx) \
+ -pady $itk_option(-pady) \
+ -bevelamount $itk_option(-bevelamount) \
+ -state $itk_option(-state) \
+ -tabborders $itk_option(-tabborders) \
+ -invert $invert \
+ -orient $orient \
+ $args
+
+ $tabName lower
+
+ $itk_component(canvas) \
+ bind $tabName <Button-1> [itcl::code $this _selectName $tabName]
+
+ incr _uniqueID
+
+ return $tabName
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _deleteTabs
+#
+# Deletes tabs from $fromTab to $toTab.
+#
+# Operates in two passes, destroys all the widgets
+# Then removes the pathName from the tab list
+#
+# Also keeps the current selection in bounds.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_deleteTabs {fromTab toTab} {
+ for { set tab $fromTab } { $tab <= $toTab } { incr tab } {
+ set tabName [lindex $_tabs $tab]
+
+ # unbind Button-1 from this window name
+ $itk_component(canvas) bind $tabName <Button-1> {}
+
+ # Destroy the Tab class...
+ itcl::delete object $tabName
+ }
+
+ # physically remove the tab
+ set _tabs [lreplace $_tabs $fromTab $toTab]
+
+ # If we deleted a selected tab set our selection to none
+ if { $_currTab >= $fromTab && $_currTab <= $toTab } {
+ set _currTab -1
+ _drawBevelBorder
+ }
+
+ # make sure _currTab stays in sync with new numbering...
+ if { $_tabs == {} } {
+ # if deleted only remaining tab,
+ # reset current tab to undefined
+ set _currTab -1
+
+ # or if the current tab was the last tab, it needs come back
+ } elseif { $_currTab >= [llength $_tabs] } {
+ incr _currTab -1
+ if { $_currTab < 0 } {
+ # but only to zero
+ set _currTab 0
+ }
+ }
+
+ _relayoutTabs
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _index
+#
+# pathList : list of path names to search thru if index is a label
+# index : either number, 'select', 'end', or pattern
+# select : current selection
+#
+# _index takes takes the value $index converts it to
+# a numeric identifier. If the value is not already
+# an integer it looks it up in the $pathList array.
+# If it fails it returns -1
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_index {pathList index select} {
+ switch $index {
+ select {
+ set number $select
+ }
+ end {
+ set number [expr {[llength $pathList] -1}]
+ }
+ default {
+ # is it an number already?
+ if { [regexp {^[0-9]+$} $index] } {
+ set number $index
+ if { $number < 0 || $number >= [llength $pathList] } {
+ set number -1
+ }
+
+ # otherwise it is a label
+ } else {
+ # look thru the pathList of pathNames and
+ # get each label and compare with index.
+ # if we get a match then set number to postion in $pathList
+ # and break out.
+ # otherwise number is still -1
+ set i 0
+ set number -1
+ foreach pathName $pathList {
+ set label [$pathName cget -label]
+ if { $label == $index } {
+ set number $i
+ break
+ }
+ incr i
+ }
+ }
+ }
+ }
+
+ return $number
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _tabConfigure
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_tabConfigure {args} {
+ foreach tab $_tabs {
+ eval $tab configure $args
+ }
+
+ set _relayout true
+
+ if { $_tabs != {} } {
+ select select
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _relayoutTabs
+#
+# relays out the tabs with correct spacing...
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_relayoutTabs {} {
+ if { [llength $_tabs] == 0 || ![winfo viewable $itk_component(hull)]} {
+ return
+ }
+
+ # get the max width for fixed width tabs...
+ set maxWidth 0
+ foreach tab $_tabs {
+ set width [$tab labelwidth]
+ if { $width > $maxWidth } {
+ set maxWidth $width
+ }
+ }
+
+ # get the max height for fixed height tabs...
+ set maxHeight 0
+ foreach tab $_tabs {
+ set height [$tab labelheight]
+ if { $height > $maxHeight } {
+ set maxHeight $height
+ }
+ }
+
+ # get curr tab's name
+ set currTabName [lindex $_tabs $_currTab]
+
+ # Start with our margin offset in pixels...
+ set tabStart $_start
+
+ if { $itk_option(-raiseselect) } {
+ set raiseAmt 2
+ } else {
+ set raiseAmt 0
+ }
+
+ #
+ # Depending on the tab layout: n, s, e, or w place the tabs
+ # according to orientation, raise, margins, etc.
+ #
+ switch $itk_option(-tabpos) {
+ n {
+ set _selectedTop [expr {$_margin + 1}]
+ set _deselectedTop [expr {$_selectedTop + $raiseAmt}]
+
+ if { $itk_option(-equaltabs) } {
+ set tabWidth $maxWidth
+ } else {
+ set tabWidth 0
+ }
+
+ foreach tab $_tabs {
+ if { $tab == $currTabName } {
+ $tab configure -left $tabStart -top $_selectedTop \
+ -height $maxHeight -width $tabWidth -anchor c
+ } else {
+ $tab configure -left $tabStart -top $_deselectedTop \
+ -height $maxHeight -width $tabWidth -anchor c
+ }
+ set tabStart [expr {$tabStart + [_calcNextTabOffset $tab]}]
+ }
+
+ }
+ s {
+ set _selectedTop 0
+ set _deselectedTop [expr {$_selectedTop - $raiseAmt}]
+
+ if { $itk_option(-equaltabs) } {
+ set tabWidth $maxWidth
+ } else {
+ set tabWidth 0
+ }
+
+ foreach tab $_tabs {
+ if { $tab == $currTabName } {
+ $tab configure -left $tabStart -top $_selectedTop \
+ -height $maxHeight -width $tabWidth -anchor c
+ } else {
+ $tab configure -left $tabStart -top $_deselectedTop \
+ -height $maxHeight -width $tabWidth -anchor c
+ }
+ set tabStart [expr {$tabStart + [_calcNextTabOffset $tab]}]
+ }
+
+ }
+ w {
+ set _selectedLeft [expr {$_margin + 1}]
+ set _deselectedLeft [expr {$_selectedLeft + $raiseAmt}]
+
+ if { $itk_option(-equaltabs) } {
+ set tabHeight $maxHeight
+ } else {
+ set tabHeight 0
+ }
+
+ foreach tab $_tabs {
+ # selected
+ if { $tab == $currTabName } {
+ $tab configure -top $tabStart -left $_selectedLeft \
+ -height $tabHeight -width $maxWidth -anchor e
+ # deselected
+ } else {
+ $tab configure -top $tabStart -left $_deselectedLeft \
+ -height $tabHeight -width $maxWidth -anchor e
+ }
+ set tabStart [expr {$tabStart + [_calcNextTabOffset $tab]}]
+ }
+
+ }
+ e {
+ set _selectedLeft 0
+ set _deselectedLeft [expr {$_selectedLeft - $raiseAmt}]
+
+ if { $itk_option(-equaltabs) } {
+ set tabHeight $maxHeight
+ } else {
+ set tabHeight 0
+ }
+
+ foreach tab $_tabs {
+ # selected
+ if { $tab == $currTabName } {
+ $tab configure -top $tabStart -left $_selectedLeft \
+ -height $tabHeight -width $maxWidth -anchor w
+ # deselected
+ } else {
+ $tab configure -top $tabStart -left $_deselectedLeft \
+ -height $tabHeight -width $maxWidth -anchor w
+ }
+ set tabStart [expr {$tabStart + [_calcNextTabOffset $tab]}]
+ }
+
+ }
+ default {
+ error "bad anchor position\
+ \"$itk_option(-tabpos)\" must be n, s, e, or w"
+ }
+ }
+
+ # put border on & calc our new canvas size...
+ _drawBevelBorder
+ _recalcCanvasGeom
+
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _drawBevelBorder
+#
+# draws the bevel border along tab edge (below selected tab)
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_drawBevelBorder {} {
+ $itk_component(canvas) delete bevelBorder
+
+ switch $itk_option(-tabpos) {
+ n {
+ $itk_component(canvas) create line \
+ 0 [expr {$_canvasHeight - 1}] \
+ $_canvasWidth [expr {$_canvasHeight - 1}] \
+ -fill [iwidgets::colors::topShadow $itk_option(-selectbackground)] \
+ -tags bevelBorder
+ $itk_component(canvas) create line \
+ 0 $_canvasHeight \
+ $_canvasWidth $_canvasHeight \
+ -fill [iwidgets::colors::topShadow $itk_option(-selectbackground)] \
+ -tags bevelBorder
+ }
+ s {
+ $itk_component(canvas) create line \
+ 0 0 \
+ $_canvasWidth 0 \
+ -fill [iwidgets::colors::bottomShadow $itk_option(-selectbackground)] \
+ -tags bevelBorder
+ $itk_component(canvas) create line \
+ 0 1 \
+ $_canvasWidth 1 \
+ -fill black \
+ -tags bevelBorder
+ }
+ w {
+ $itk_component(canvas) create line \
+ $_canvasWidth 0 \
+ $_canvasWidth [expr {$_canvasHeight - 1}] \
+ -fill [iwidgets::colors::topShadow $itk_option(-selectbackground)] \
+ -tags bevelBorder
+ $itk_component(canvas) create line \
+ [expr {$_canvasWidth - 1}] 0 \
+ [expr {$_canvasWidth - 1}] [expr {$_canvasHeight - 1}] \
+ -fill [iwidgets::colors::topShadow $itk_option(-selectbackground)] \
+ -tags bevelBorder
+
+ }
+ e {
+ $itk_component(canvas) create line \
+ 0 0 \
+ 0 [expr {$_canvasHeight - 1}] \
+ -fill black \
+ -tags bevelBorder
+ $itk_component(canvas) create line \
+ 1 0 \
+ 1 [expr {$_canvasHeight - 1}] \
+ -fill [iwidgets::colors::bottomShadow $itk_option(-selectbackground)] \
+ -tags bevelBorder
+
+ }
+ }
+
+ $itk_component(canvas) raise bevelBorder
+ if { $_currTab != -1 } {
+ set currTabName [lindex $_tabs $_currTab]
+ $currTabName raise
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _calcNextTabOffset
+#
+# given $tabName, determines the offset in pixels to place
+# the next tab's start edge at.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_calcNextTabOffset {tabName} {
+ if { $_gap == "overlap" } {
+ return [$tabName offset]
+ } else {
+ return [expr {[$tabName majordim] + $_gap}]
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _tabBounds
+#
+# calculates the bounding box that will completely enclose
+# all the tabs.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_tabBounds {} {
+ set bbox { 100000 100000 -10000 -10000 }
+ foreach tab $_tabs {
+ set tabBBox [$tab bbox]
+ # if this left is less use it
+ if { [lindex $tabBBox 0] < [lindex $bbox 0] } {
+ set bbox [lreplace $bbox 0 0 [lindex $tabBBox 0]]
+ }
+ # if this top is greater use it
+ if { [lindex $tabBBox 1] < [lindex $bbox 1] } {
+ set bbox [lreplace $bbox 1 1 [lindex $tabBBox 1]]
+ }
+ # if this right is less use it
+ if { [lindex $tabBBox 2] > [lindex $bbox 2] } {
+ set bbox [lreplace $bbox 2 2 [lindex $tabBBox 2]]
+ }
+ # if this bottom is greater use it
+ if { [lindex $tabBBox 3] > [lindex $bbox 3] } {
+ set bbox [lreplace $bbox 3 3 [lindex $tabBBox 3]]
+ }
+
+ }
+ return $bbox
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _recalcCanvasGeom
+#
+# Based on size of tabs, recalculates the canvas geometry that
+# will hold the tabs.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_recalcCanvasGeom {} {
+ if { [llength $_tabs] == 0 } {
+ return
+ }
+
+ set bbox [_tabBounds]
+
+ set width [lindex [_tabBounds] 2]
+ set height [lindex [_tabBounds] 3]
+
+ # now we have the dimensions of all the tabs in the canvas.
+
+
+ switch $itk_option(-tabpos) {
+ n {
+ # height already includes margin
+ $itk_component(canvas) configure \
+ -width $width \
+ -height $height
+ }
+ s {
+ $itk_component(canvas) configure \
+ -width $width \
+ -height [expr {$height + $_margin}]
+ }
+ w {
+ # width already includes margin
+ $itk_component(canvas) configure \
+ -width $width \
+ -height [expr {$height + 1}]
+ }
+ e {
+ $itk_component(canvas) configure \
+ -width [expr {$width + $_margin}] \
+ -height [expr {$height + 1}]
+ }
+ default {
+ }
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _canvasReconfigure
+#
+# Bound to the reconfigure notify event of a canvas, this
+# method resets canvas's correct width (since we are fill x)
+# and redraws the beveled edge border.
+# will hold the tabs.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_canvasReconfigure {width height} {
+ set _canvasWidth $width
+ set _canvasHeight $height
+
+ if { [llength $_tabs] > 0 } {
+ _drawBevelBorder
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _startMove
+#
+# This method is bound to the MB2 down in the canvas area of the
+# tab set. This starts animated scrolling of the tabs along their
+# major axis.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_startMove {x y} {
+ if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s" } {
+ set _anchorX $x
+ } else {
+ set _anchorY $y
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _moveTabs
+#
+# This method is bound to the MB2 motion in the canvas area of the
+# tab set. This causes the tabset to move with the mouse.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_moveTabs {x y} {
+ if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s" } {
+ set startX [expr {$_start + $x - $_anchorX}]
+ foreach tab $_tabs {
+ $tab configure -left $startX
+ set startX [expr {$startX + [_calcNextTabOffset $tab]}]
+ }
+ } else {
+ set startY [expr {$_start + $y - $_anchorY}]
+ foreach tab $_tabs {
+ $tab configure -top $startY
+ set startY [expr {$startY + [_calcNextTabOffset $tab]}]
+ }
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _endMove
+#
+# This method is bound to the MB2 release in the canvas area of the
+# tab set. This causes the tabset to end moving tabs.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tabset::_endMove {x y} {
+ if { $itk_option(-tabpos) == "n" || $itk_option(-tabpos) == "s" } {
+ set startX [expr {$_start + $x - $_anchorX}]
+ set _skipRelayout true
+ configure -start $startX
+ set _skipRelayout false
+ } else {
+ set startY [expr {$_start + $y - $_anchorY}]
+ set _skipRelayout true
+ configure -start $startY
+ set _skipRelayout false
+ }
+}
+
+
+#==============================================================
+# CLASS: Tab
+#==============================================================
+
+itcl::class iwidgets::Tab {
+ constructor {args} {}
+
+ destructor {}
+
+ public variable bevelamount 0 {}
+ public variable state normal {}
+ public variable height 0 {}
+ public variable width 0 {}
+ public variable anchor c {}
+ public variable left 0 {}
+ public variable top 0 {}
+ public variable image {} {}
+ public variable bitmap {} {}
+ public variable label {} {}
+ public variable padx 4 {}
+ public variable pady 4 {}
+ public variable selectbackground "gray70" {}
+ public variable selectforeground "black" {}
+ public variable disabledforeground "gray" {}
+ public variable background "white" {}
+ public variable foreground "black" {}
+ public variable orient vertical {}
+ public variable invert false {}
+ public variable angle 20 {}
+ public variable font \
+ "-adobe-helvetica-bold-r-normal--34-240-100-100-p-182-iso8859-1" {}
+ public variable tabborders true {}
+
+ public method configure {args}
+ public method bbox {}
+ public method deselect {}
+ public method lower {}
+ public method majordim {}
+ public method minordim {}
+ public method offset {}
+ public method raise {}
+ public method select {}
+ public method labelheight {}
+ public method labelwidth {}
+
+ private method _makeTab {}
+ private method _createLabel {canvas tagList}
+ private method _makeEastTab {canvas}
+ private method _makeWestTab {canvas}
+ private method _makeNorthTab {canvas}
+ private method _makeSouthTab {canvas}
+ private method _calcLabelDim {labelItem}
+ private method _itk_config {args} @itcl-builtin-configure
+ private method _selectNoRaise {}
+ private method _deselectNoLower {}
+
+ private variable _selected false
+ private variable _padX 0
+ private variable _padY 0
+
+ private variable _canvas
+
+ # these are in pixels
+ private variable _left 0
+ private variable _width 0
+ private variable _height 0
+ private variable _oldLeft 0
+ private variable _top 0
+ private variable _oldTop 0
+
+ private variable _right
+ private variable _bottom
+
+ private variable _offset
+ private variable _majorDim
+ private variable _minorDim
+
+ private variable _darkShadow
+ private variable _lightShadow
+
+ #
+ # graphic components that make up a tab
+ #
+ private variable _gRegion
+ private variable _gLabel
+ private variable _gLightOutline {}
+ private variable _gBlackOutline {}
+ private variable _gTopLine
+ private variable _gTopLineShadow
+ private variable _gLightShadow
+ private variable _gDarkShadow
+
+ private variable _labelWidth 0
+ private variable _labelHeight 0
+
+ private variable _labelXOrigin 0
+ private variable _labelYOrigin 0
+
+ private variable _just left
+
+ private variable _configTripped true
+
+ common _tan
+
+ set _tan(0) 0.0
+ set _tan(1) 0.0175
+ set _tan(2) 0.0349
+ set _tan(3) 0.0524
+ set _tan(4) 0.0699
+ set _tan(5) 0.0875
+ set _tan(6) 0.1051
+ set _tan(7) 0.1228
+ set _tan(8) 0.1405
+ set _tan(9) 0.1584
+ set _tan(10) 0.1763
+ set _tan(11) 0.1944
+ set _tan(12) 0.2126
+ set _tan(13) 0.2309
+ set _tan(14) 0.2493
+ set _tan(15) 0.2679
+ set _tan(16) 0.2867
+ set _tan(17) 0.3057
+ set _tan(18) 0.3249
+ set _tan(19) 0.3443
+ set _tan(20) 0.3640
+ set _tan(21) 0.3839
+ set _tan(22) 0.4040
+ set _tan(23) 0.4245
+ set _tan(24) 0.4452
+ set _tan(25) 0.4663
+ set _tan(26) 0.4877
+ set _tan(27) 0.5095
+ set _tan(28) 0.5317
+ set _tan(29) 0.5543
+ set _tan(30) 0.5774
+ set _tan(31) 0.6009
+ set _tan(32) 0.6294
+ set _tan(33) 0.6494
+ set _tan(34) 0.6745
+ set _tan(35) 0.7002
+ set _tan(36) 0.7265
+ set _tan(37) 0.7536
+ set _tan(38) 0.7813
+ set _tan(39) 0.8098
+ set _tan(40) 0.8391
+ set _tan(41) 0.8693
+ set _tan(42) 0.9004
+ set _tan(43) 0.9325
+ set _tan(44) 0.9657
+ set _tan(45) 1.0
+}
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::constructor {args} {
+
+ set _canvas [lindex $args 0]
+ set args [lrange $args 1 [llength $args]]
+
+ set _darkShadow [iwidgets::colors::bottomShadow $selectbackground]
+ set _lightShadow [iwidgets::colors::topShadow $selectbackground]
+
+ if { $args != "" } {
+ eval configure $args
+ }
+}
+
+# ----------------------------------------------------------------------
+# DESTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::destructor {} {
+ if { [winfo exists $_canvas] } {
+ $_canvas delete $this
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTIONS
+# ----------------------------------------------------------------------
+#
+# Note, we trip _configTripped for every option that requires the tab
+# to be remade.
+#
+# ----------------------------------------------------------------------
+# OPTION -bevelamount
+#
+# Specifies the size of tab corners. A value of 0 with angle set
+# to 0 results in square tabs. A bevelAmount of 4, means that the
+# tab will be drawn with angled corners that cut in 4 pixels from
+# the edge of the tab. The default is 0.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::bevelamount {
+}
+
+# ----------------------------------------------------------------------
+# OPTION -state
+#
+# sets the active state of the tab. specifying normal allows
+# the tab to be selectable. Specifying disabled disables the tab,
+# causing its image, bitmap, or label to be drawn with the
+# disabledForeground color.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::state {
+}
+
+# ----------------------------------------------------------------------
+# OPTION -height
+#
+# the height of the tab. if 0, uses the font label height.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::height {
+ set _height [winfo pixels $_canvas $height]
+ set _configTripped true
+}
+
+# ----------------------------------------------------------------------
+# OPTION -width
+#
+# The width of the tab. If 0, uses the font label width.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::width {
+ set _width [winfo pixels $_canvas $width]
+ set _configTripped true
+}
+
+# ----------------------------------------------------------------------
+# OPTION -anchor
+#
+# Where the text in the tab will be anchored: n,nw,ne,s,sw,se,e,w,center
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::anchor {
+}
+
+# ----------------------------------------------------------------------
+# OPTION -left
+#
+# Specifies the left edge of the tab's bounding box. This value
+# may have any of the forms acceptable to Tk_GetPixels.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::left {
+
+ # get into pixels
+ set _left [winfo pixels $_canvas $left]
+
+ # move by offset from last setting
+ $_canvas move $this [expr {$_left - $_oldLeft}] 0
+
+ # update old for next time
+ set _oldLeft $_left
+}
+
+# ----------------------------------------------------------------------
+# OPTION -top
+#
+# Specifies the topedge of the tab's bounding box. This value may
+# have any of the forms acceptable to Tk_GetPixels.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::top {
+
+ # get into pixels
+ set _top [winfo pixels $_canvas $top]
+
+ # move by offset from last setting
+ $_canvas move $this 0 [expr {$_top - $_oldTop}]
+
+ # update old for next time
+ set _oldTop $_top
+}
+
+# ----------------------------------------------------------------------
+# OPTION -image
+#
+# Specifies the imageto display in the tab.
+# Images are created with the image create command.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::image {
+ set _configTripped true
+}
+
+# ----------------------------------------------------------------------
+# OPTION -bitmap
+#
+# If bitmap is an empty string, specifies the bitmap to display in
+# the tab. Bitmap may be of any of the forms accepted by Tk_GetBitmap.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::bitmap {
+ set _configTripped true
+}
+
+# ----------------------------------------------------------------------
+# OPTION -label
+#
+# If image is an empty string and bitmap is an empty string,
+# it specifies a text string to be placed in the tab's label.
+# This label serves as an additional identifier used to reference
+# the tab. Label may be used for the index value in widget commands.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::label {
+ set _configTripped true
+}
+
+# ----------------------------------------------------------------------
+# OPTION -padx
+#
+# Horizontal padding around the label (text, image, or bitmap).
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::padx {
+ set _configTripped true
+ set _padX [winfo pixels $_canvas $padx]
+}
+
+# ----------------------------------------------------------------------
+# OPTION -pady
+#
+# Vertical padding around the label (text, image, or bitmap).
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::pady {
+ set _configTripped true
+ set _padY [winfo pixels $_canvas $pady]
+}
+
+# ----------------------------------------------------------------------
+# OPTION -selectbackground
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::selectbackground {
+ set _darkShadow [iwidgets::colors::bottomShadow $selectbackground]
+ set _lightShadow [iwidgets::colors::topShadow $selectbackground]
+
+ if { $_selected } {
+ _selectNoRaise
+ } else {
+ _deselectNoLower
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -selectforeground
+#
+# Foreground of tab when selected
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::selectforeground {
+ if { $_selected } {
+ _selectNoRaise
+ } else {
+ _deselectNoLower
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -disabledforeground
+#
+# Background of tab when -state is disabled
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::disabledforeground {
+ if { $_selected } {
+ _selectNoRaise
+ } else {
+ _deselectNoLower
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -background
+#
+# Normal background of tab.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::background {
+
+ if { $_selected } {
+ _selectNoRaise
+ } else {
+ _deselectNoLower
+ }
+
+}
+
+# ----------------------------------------------------------------------
+# OPTION -foreground
+#
+# Foreground of tabs when in normal unselected state
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::foreground {
+ if { $_selected } {
+ _selectNoRaise
+ } else {
+ _deselectNoLower
+ }
+}
+
+# ----------------------------------------------------------------------
+# OPTION -orient
+#
+# Specifies the orientation of the tab. Orient can be either
+# horizontal or vertical.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::orient {
+ set _configTripped true
+}
+
+# ----------------------------------------------------------------------
+# OPTION -invert
+#
+# Specifies the direction to draw the tab. If invert is true,
+# it draws horizontal tabs upside down and vertical tabs opening
+# to the left (pointing right). The value may have any of the
+# forms accepted by the Tcl_GetBoolean, such as true,
+# false, 0, 1, yes, or no.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::invert {
+ set _configTripped true
+}
+
+# ----------------------------------------------------------------------
+# OPTION -angle
+#
+# Specifes the angle of slope from the inner edge to the outer edge
+# of the tab. An angle of 0 specifies square tabs. Valid ranges are
+# 0 to 45 degrees inclusive. Default is 15 degrees. If this option
+# is specified as an empty string (the default), then the angle
+# option for the overall Tabset is used.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::angle {
+ if {$angle < 0 || $angle > 45 } {
+ error "bad angle: must be between 0 and 45"
+ }
+ set _configTripped true
+}
+
+# ----------------------------------------------------------------------
+# OPTION -font
+#
+# Font for tab text.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::font {
+}
+
+
+# ----------------------------------------------------------------------
+# OPTION -tabborders
+#
+# Specifies whether to draw the borders of a deselected tab.
+# Specifying true (the default) draws these borders,
+# specifying false disables this drawing. If the tab is in
+# its selected state this option has no effect.
+# The value may have any of the forms accepted by the
+# Tcl_GetBoolean, such as true, false, 0, 1, yes, or no.
+# ----------------------------------------------------------------------
+itcl::configbody iwidgets::Tab::tabborders {
+ set _configTripped true
+}
+
+# ----------------------------------------------------------------------
+# METHOD: configure ?option value?
+#
+# Configures the Tab, checks a configTripped flag to see if the tab
+# needs to be remade. We take the easy way since it is so inexpensive
+# to delete canvas items and remake them.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::configure {args} {
+ set len [llength $args]
+
+ switch $len {
+ 0 {
+ set result [_itk_config]
+ return $result
+ }
+ 1 {
+ set result [eval _itk_config $args]
+ return $result
+ }
+ default {
+ eval _itk_config $args
+ if { $_configTripped } {
+ _makeTab
+ set _configTripped false
+ }
+ return ""
+ }
+ }
+}
+
+# ----------------------------------------------------------------------
+# METHOD: bbox
+#
+# Returns the bounding box of the tab
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::bbox {} {
+ return [lappend bbox $_left $_top $_right $_bottom]
+}
+# ----------------------------------------------------------------------
+# METHOD: deselect
+#
+# Causes the given tab to be drawn as deselected and lowered
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::deselect {} {
+ global tcl_platform
+ $_canvas lower $this
+
+ if {$tcl_platform(os) == "HP-UX"} {
+ update idletasks
+ }
+
+ _deselectNoLower
+}
+
+# ----------------------------------------------------------------------
+# METHOD: lower
+#
+# Lowers the tab below all others in the canvas.
+#
+# This is used as our tag name on the canvas.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::lower {} {
+ $_canvas lower $this
+}
+
+# ----------------------------------------------------------------------
+# METHOD: majordim
+#
+# Returns the width for horizontal tabs and the height for
+# vertical tabs.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::majordim {} {
+ return $_majorDim
+}
+
+# ----------------------------------------------------------------------
+# METHOD: minordim
+#
+# Returns the height for horizontal tabs and the width for
+# vertical tabs.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::minordim {} {
+ return $_minorDim
+}
+
+# ----------------------------------------------------------------------
+# METHOD: offset
+#
+# Returns the width less the angle offset. This allows a
+# geometry manager to ask where to place a sibling tab.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::offset {} {
+ return $_offset
+}
+
+# ----------------------------------------------------------------------
+# METHOD: raise
+#
+# Raises the tab above all others in the canvas.
+#
+# This is used as our tag name on the canvas.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::raise {} {
+ $_canvas raise $this
+}
+
+# ----------------------------------------------------------------------
+# METHOD: select
+#
+# Causes the given tab to be drawn as selected. 3d shadows are
+# turned on and top line and top line shadow are drawn in sel
+# bg color to hide them.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::select {} {
+ global tcl_platform
+ $_canvas raise $this
+
+ if {$tcl_platform(os) == "HP-UX"} {
+ update idletasks
+ }
+
+ _selectNoRaise
+}
+
+# ----------------------------------------------------------------------
+# METHOD: labelheight
+#
+# Returns the height of the tab's label in its current font.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::labelheight {} {
+ if {$_gLabel != 0} {
+ set labelBBox [$_canvas bbox $_gLabel]
+ set labelHeight [expr {[lindex $labelBBox 3] - [lindex $labelBBox 1]}]
+ } else {
+ set labelHeight 0
+ }
+ return $labelHeight
+}
+
+# ----------------------------------------------------------------------
+# METHOD: labelwidth
+#
+# Returns the width of the tab's label in its current font.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::labelwidth {} {
+ if {$_gLabel != 0} {
+ set labelBBox [$_canvas bbox $_gLabel]
+ set labelWidth [expr {[lindex $labelBBox 2] - [lindex $labelBBox 0]}]
+ } else {
+ set labelWidth 0
+ }
+ return $labelWidth
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _selectNoRaise
+#
+# Draws tab as selected without raising it.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::_selectNoRaise {} {
+ if { ! [info exists _gRegion] } {
+ return
+ }
+
+ $_canvas itemconfigure $_gRegion -fill $selectbackground
+ $_canvas itemconfigure $_gTopLine -fill $selectbackground
+ $_canvas itemconfigure $_gTopLineShadow -fill $selectbackground
+ $_canvas itemconfigure $_gLightShadow -fill $_lightShadow
+ $_canvas itemconfigure $_gDarkShadow -fill $_darkShadow
+
+ if { $_gLightOutline != {} } {
+ $_canvas itemconfigure $_gLightOutline -fill $_lightShadow
+ }
+ if { $_gBlackOutline != {} } {
+ $_canvas itemconfigure $_gBlackOutline -fill black
+ }
+
+ if { $state == "normal" } {
+ if { $image != {}} {
+ # do nothing for now
+ } elseif { $bitmap != {}} {
+ $_canvas itemconfigure $_gLabel \
+ -foreground $selectforeground \
+ -background $selectbackground
+ } else {
+ $_canvas itemconfigure $_gLabel -fill $selectforeground
+ }
+ } else {
+ if { $image != {}} {
+ # do nothing for now
+ } elseif { $bitmap != {}} {
+ $_canvas itemconfigure $_gLabel \
+ -foreground $disabledforeground \
+ -background $selectbackground
+ } else {
+ $_canvas itemconfigure $_gLabel -fill $disabledforeground
+ }
+ }
+
+ set _selected true
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _deselectNoLower
+#
+# Causes the given tab to be drawn as deselected. 3d shadows are
+# removed and top line and top line shadow are drawn in visible
+# colors to reveal them.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::_deselectNoLower {} {
+ if { ! [info exists _gRegion] } {
+ return
+ }
+
+ $_canvas itemconfigure $_gRegion -fill $background
+ $_canvas itemconfigure $_gTopLine -fill black
+ $_canvas itemconfigure $_gTopLineShadow -fill $_darkShadow
+ $_canvas itemconfigure $_gLightShadow -fill $background
+ $_canvas itemconfigure $_gDarkShadow -fill $background
+
+ if { $tabborders } {
+ if { $_gLightOutline != {} } {
+ $_canvas itemconfigure $_gLightOutline -fill $_lightShadow
+ }
+ if { $_gBlackOutline != {} } {
+ $_canvas itemconfigure $_gBlackOutline -fill black
+ }
+ } else {
+ if { $_gLightOutline != {} } {
+ $_canvas itemconfigure $_gLightOutline -fill $background
+ }
+ if { $_gBlackOutline != {} } {
+ $_canvas itemconfigure $_gBlackOutline -fill $background
+ }
+ }
+
+
+ if { $state == "normal" } {
+ if { $image != {}} {
+ # do nothing for now
+ } elseif { $bitmap != {}} {
+ $_canvas itemconfigure $_gLabel \
+ -foreground $foreground \
+ -background $background
+ } else {
+ $_canvas itemconfigure $_gLabel -fill $foreground
+ }
+ } else {
+ if { $image != {}} {
+ # do nothing for now
+ } elseif { $bitmap != {}} {
+ $_canvas itemconfigure $_gLabel \
+ -foreground $disabledforeground \
+ -background $background
+ } else {
+ $_canvas itemconfigure $_gLabel -fill $disabledforeground
+ }
+ }
+
+ set _selected false
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _makeTab
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::_makeTab {} {
+ if { $orient == "horizontal" } {
+ if { $invert } {
+ _makeNorthTab $_canvas
+ } else {
+ _makeSouthTab $_canvas
+ }
+ } elseif { $orient == "vertical" } {
+ if { $invert } {
+ _makeEastTab $_canvas
+ } else {
+ _makeWestTab $_canvas
+ }
+ } else {
+ error "bad value for option -orient"
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _createLabel
+#
+# Creates the label for the tab. Can be either a text label
+# or a bitmap label.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::_createLabel {canvas tagList} {
+ if { $image != {}} {
+ set _gLabel [$canvas create image \
+ 0 0 \
+ -image $image \
+ -anchor nw \
+ -tags $tagList \
+ ]
+ } elseif { $bitmap != {}} {
+ set _gLabel [$canvas create bitmap \
+ 0 0 \
+ -bitmap $bitmap \
+ -anchor nw \
+ -tags $tagList \
+ ]
+ } else {
+ set _gLabel [$canvas create text \
+ 0 0 \
+ -text $label \
+ -font $font \
+ -anchor nw \
+ -tags $tagList \
+ ]
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _makeEastTab
+#
+# Makes a tab that hangs to the east and opens to the west.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::_makeEastTab {canvas} {
+ $canvas delete $this
+ set _gLightOutline {}
+ set _gBlackOutline {}
+
+ lappend tagList $this TAB
+
+ _createLabel $canvas $tagList
+
+ _calcLabelDim $_gLabel
+
+
+ set right [expr {$_left + $_labelWidth}]
+ # now have _left, _top, right...
+
+ # Turn off calculating angle tabs on Vertical orientations
+ set angleOffset 0
+
+ set outerTop $_top
+ set outerBottom \
+ [expr {$outerTop + $angleOffset + $_labelHeight + $angleOffset}]
+ set innerTop [expr {$outerTop + $angleOffset}]
+ set innerBottom [expr {$outerTop + $angleOffset + $_labelHeight}]
+
+ # now have _left, _top, right, outerTop, innerTop,
+ # innerBottom, outerBottom, width, height
+
+ set bottom $innerBottom
+ # tab area... gets filled either white or selected
+ # done
+ set _gRegion [$canvas create polygon \
+ $_left $outerTop \
+ [expr {$right - $bevelamount}] $innerTop \
+ $right [expr {$innerTop + $bevelamount}] \
+ $right [expr {$innerBottom - $bevelamount}] \
+ [expr {$right - $bevelamount}] $innerBottom \
+ $_left $outerBottom \
+ $_left $outerTop \
+ -tags $tagList \
+ ]
+
+ # lighter shadow (left edge)
+ set _gLightShadow [$canvas create line \
+ [expr {$_left - 3}] [expr {$outerTop + 1}] \
+ [expr {$right - $bevelamount}] [expr {$innerTop + 1}] \
+ -tags $tagList \
+ ]
+
+ # darker shadow (bottom and right edges)
+ set _gDarkShadow [$canvas create line \
+ [expr {$right - $bevelamount}] [expr {$innerTop + 1}] \
+ [expr {$right - 1}] [expr {$innerTop + $bevelamount}] \
+ [expr {$right - 1}] [expr {$innerBottom - $bevelamount}] \
+ [expr {$right - $bevelamount}] [expr {$innerBottom - 1}] \
+ [expr {$_left - 3}] [expr {$outerBottom - 1}] \
+ -tags $tagList \
+ ]
+
+ # outline of tab
+ set _gLightOutline [$canvas create line \
+ $_left $outerTop \
+ [expr {$right - $bevelamount}] $innerTop \
+ -tags $tagList \
+ ]
+ # outline of tab
+ set _gBlackOutline [$canvas create line \
+ [expr {$right - $bevelamount}] $innerTop \
+ $right [expr {$innerTop + $bevelamount}] \
+ $right [expr {$innerBottom - $bevelamount}] \
+ [expr {$right - $bevelamount}] $innerBottom \
+ $_left $outerBottom \
+ $_left $outerTop \
+ -tags $tagList \
+ ]
+
+ # line closest to the edge
+ set _gTopLineShadow [$canvas create line \
+ $_left $outerTop \
+ $_left $outerBottom \
+ -tags $tagList \
+ ]
+
+ # next line down
+ set _gTopLine [$canvas create line \
+ [expr {$_left + 1}] [expr {$outerTop + 2}] \
+ [expr {$_left + 1}] [expr {$outerBottom - 1}] \
+ -tags $tagList \
+ ]
+
+ $canvas coords $_gLabel [expr {$_left + $_labelXOrigin}] \
+ [expr {$innerTop + $_labelYOrigin}]
+
+ if { $image != {} || $bitmap != {} } {
+ $canvas itemconfigure $_gLabel -anchor $anchor
+ } else {
+ $canvas itemconfigure $_gLabel -anchor $anchor -justify $_just
+ }
+
+ $canvas raise $_gLabel $_gRegion
+
+
+ set _offset [expr {$innerBottom - $outerTop}]
+ # height
+ set _majorDim [expr {$outerBottom - $outerTop}]
+ # width
+ set _minorDim [expr {$right - $_left}]
+
+ set _right $right
+ set _bottom $outerBottom
+
+ # draw in correct state...
+ if { $_selected } {
+ select
+ } else {
+ deselect
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _makeWestTab
+#
+# Makes a tab that hangs to the west and opens to the east.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::_makeWestTab {canvas} {
+ $canvas delete $this
+ set _gLightOutline {}
+ set _gBlackOutline {}
+
+ lappend tagList $this TAB
+
+ _createLabel $canvas $tagList
+ _calcLabelDim $_gLabel
+
+ set right [expr {$_left + $_labelWidth}]
+ # now have _left, _top, right...
+
+ # Turn off calculating angle tabs on Vertical orientations
+ set angleOffset 0
+
+ set outerTop $_top
+ set outerBottom \
+ [expr {$outerTop + $angleOffset + $_labelHeight + $angleOffset}]
+ set innerTop [expr {$outerTop + $angleOffset}]
+ set innerBottom [expr {$outerTop + $angleOffset + $_labelHeight}]
+
+ # now have _left, _top, right, outerTop, innerTop,
+ # innerBottom, outerBottom, width, height
+
+ # tab area... gets filled either white or selected
+ # done
+ set _gRegion [$canvas create polygon \
+ $right $outerTop \
+ [expr {$_left + $bevelamount}] $innerTop \
+ $_left [expr {$innerTop + $bevelamount}] \
+ $_left [expr {$innerBottom - $bevelamount}]\
+ [expr {$_left + $bevelamount}] $innerBottom \
+ $right $outerBottom \
+ $right $outerTop \
+ -tags $tagList \
+ ]
+ # lighter shadow (left edge)
+ set _gLightShadow [$canvas create line \
+ $right [expr {$outerTop+1}] \
+ [expr {$_left + $bevelamount}] [expr {$innerTop + 1}] \
+ [expr {$_left + 1}] [expr {$innerTop + $bevelamount}] \
+ [expr {$_left + 1}] [expr {$innerBottom - $bevelamount}] \
+ -tags $tagList \
+ ]
+
+ # darker shadow (bottom and right edges)
+ set _gDarkShadow [$canvas create line \
+ [expr {$_left + 1}] [expr {$innerBottom - $bevelamount}] \
+ [expr {$_left + $bevelamount}] [expr {$innerBottom - 1}] \
+ $right [expr {$outerBottom - 1}] \
+ -tags $tagList \
+ ]
+
+ # outline of tab -- lighter top left sides
+ set _gLightOutline [$canvas create line \
+ $right $outerTop \
+ [expr {$_left + $bevelamount}] $innerTop \
+ $_left [expr {$innerTop + $bevelamount}] \
+ $_left [expr {$innerBottom - $bevelamount}]\
+ -tags $tagList \
+ ]
+ # outline of tab -- darker bottom side
+ set _gBlackOutline [$canvas create line \
+ $_left [expr {$innerBottom - $bevelamount}]\
+ [expr {$_left + $bevelamount}] $innerBottom \
+ $right $outerBottom \
+ $right $outerTop \
+ -tags $tagList \
+ ]
+
+ # top of tab
+ set _gTopLine [$canvas create line \
+ [expr {$right + 1}] $outerTop \
+ [expr {$right + 1}] $outerBottom \
+ -tags $tagList \
+ ]
+
+ # line below top of tab
+ set _gTopLineShadow [$canvas create line \
+ $right $outerTop \
+ $right $outerBottom \
+ -tags $tagList \
+ ]
+
+ $canvas coords $_gLabel [expr {$_left + $_labelXOrigin}] \
+ [expr {$innerTop + $_labelYOrigin}]
+ if { $image != {} || $bitmap != {} } {
+ $canvas itemconfigure $_gLabel -anchor $anchor
+ } else {
+ $canvas itemconfigure $_gLabel -anchor $anchor -justify $_just
+ }
+
+ $canvas raise $_gLabel $_gRegion
+
+
+ set _offset [expr {$innerBottom - $outerTop}]
+ # height
+ set _majorDim [expr {$outerBottom - $outerTop}]
+ # width
+ set _minorDim [expr {$right - $_left}]
+
+ set _right $right
+ set _bottom $outerBottom
+
+ # draw in correct state...
+ if { $_selected } {
+ select
+ } else {
+ deselect
+ }
+
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _makeNorthTab
+#
+# Makes a tab that hangs to the north and opens to the south.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::_makeNorthTab {canvas} {
+ $canvas delete $this
+ set _gLightOutline {}
+ set _gBlackOutline {}
+
+ lappend tagList $this TAB
+
+ _createLabel $canvas $tagList
+
+ # first get the label width and height
+ _calcLabelDim $_gLabel
+
+ set bottom [expr {$_top + $_labelHeight}]
+
+ set angleOffset [expr {$_labelHeight * $_tan($angle)}]
+
+ set outerLeft $_left
+ set outerRight \
+ [expr {$outerLeft + $angleOffset + $_labelWidth + $angleOffset}]
+ set innerLeft [expr {$outerLeft + $angleOffset}]
+ set innerRight [expr {$outerLeft + $angleOffset + $_labelWidth}]
+
+ # tab area... gets filled either white or selected
+ set _gRegion [$canvas create polygon \
+ $outerLeft [expr {$bottom + 3}] \
+ $innerLeft [expr {$_top + $bevelamount}] \
+ [expr {$innerLeft + $bevelamount}] $_top \
+ [expr {$innerRight - $bevelamount}] $_top \
+ $innerRight [expr {$_top + $bevelamount}]\
+ $outerRight [expr {$bottom + 3}] \
+ $outerLeft [expr {$bottom + 3}] \
+ -tags $tagList \
+ ]
+
+ # lighter shadow (left edge)
+ set _gLightShadow [$canvas create line \
+ [expr {$outerLeft + 1}] [expr {$bottom + 3}] \
+ [expr {$innerLeft + 1}] [expr {$_top + $bevelamount}] \
+ [expr {$innerLeft + $bevelamount}] [expr {$_top + 1}]\
+ [expr {$innerRight - $bevelamount}] [expr {$_top + 1}]\
+ -tags $tagList \
+ ]
+
+ # darker shadow (bottom and right edges)
+ set _gDarkShadow [$canvas create line \
+ [expr {$innerRight - $bevelamount}] [expr {$_top + 1}]\
+ [expr {$innerRight - 1}] [expr {$_top + $bevelamount}]\
+ [expr {$outerRight - 1}] [expr {$bottom + 3}]\
+ -tags $tagList \
+ ]
+
+ set _gLightOutline [$canvas create line \
+ $outerLeft [expr {$bottom + 3}] \
+ $innerLeft [expr {$_top + $bevelamount}] \
+ [expr {$innerLeft + $bevelamount}] $_top \
+ [expr {$innerRight - $bevelamount}] $_top \
+ -tags $tagList \
+ ]
+
+ set _gBlackOutline [$canvas create line \
+ [expr {$innerRight - $bevelamount}] $_top \
+ $innerRight [expr {$_top + $bevelamount}]\
+ $outerRight [expr {$bottom + 3}] \
+ $outerLeft [expr {$bottom + 3}] \
+ -tags $tagList \
+ ]
+
+ # top of tab... to make it closed off
+ set _gTopLine [$canvas create line \
+ 0 0 0 0\
+ -tags $tagList \
+ ]
+
+ # top of tab... to make it closed off
+ set _gTopLineShadow [$canvas create line \
+ 0 0 0 0 \
+ -tags $tagList \
+ ]
+
+ $canvas coords $_gLabel [expr {$innerLeft + $_labelXOrigin}] \
+ [expr {$_top + $_labelYOrigin}]
+
+ if { $image != {} || $bitmap != {} } {
+ $canvas itemconfigure $_gLabel -anchor $anchor
+ } else {
+ $canvas itemconfigure $_gLabel -anchor $anchor -justify $_just
+ }
+
+ $canvas raise $_gLabel $_gRegion
+
+
+ set _offset [expr {$innerRight - $outerLeft}]
+ # width
+ set _majorDim [expr {$outerRight - $outerLeft}]
+ # height
+ set _minorDim [expr {$bottom - $_top}]
+
+ set _right $outerRight
+ set _bottom $bottom
+
+ # draw in correct state...
+ if { $_selected } {
+ select
+ } else {
+ deselect
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _makeSouthTab
+#
+# Makes a tab that hangs to the south and opens to the north.
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::_makeSouthTab {canvas} {
+ $canvas delete $this
+ set _gLightOutline {}
+ set _gBlackOutline {}
+
+ lappend tagList $this TAB
+
+ _createLabel $canvas $tagList
+
+ # first get the label width and height
+ _calcLabelDim $_gLabel
+
+ set bottom [expr {$_top + $_labelHeight}]
+
+ set angleOffset [expr {$_labelHeight * $_tan($angle)}]
+
+ set outerLeft $_left
+ set outerRight \
+ [expr {$outerLeft + $angleOffset + $_labelWidth + $angleOffset}]
+ set innerLeft [expr {$outerLeft + $angleOffset}]
+ set innerRight [expr {$outerLeft + $angleOffset + $_labelWidth}]
+
+ # tab area... gets filled either white or selected
+ set _gRegion [$canvas create polygon \
+ $outerLeft [expr {$_top + 1}] \
+ $innerLeft [expr {$bottom - $bevelamount}]\
+ [expr {$innerLeft + $bevelamount}] $bottom \
+ [expr {$innerRight - $bevelamount}] $bottom \
+ $innerRight [expr {$bottom - $bevelamount}]\
+ $outerRight [expr {$_top + 1}] \
+ $outerLeft [expr {$_top + 1}] \
+ -tags $tagList \
+ ]
+
+
+ # lighter shadow (left edge)
+ set _gLightShadow [$canvas create line \
+ [expr {$outerLeft+1}] $_top \
+ [expr {$innerLeft+1}] [expr {$bottom-$bevelamount}] \
+ -tags $tagList \
+ ]
+
+ # darker shadow (bottom and right edges)
+ set _gDarkShadow [$canvas create line \
+ [expr {$innerLeft+1}] [expr {$bottom-$bevelamount}] \
+ [expr {$innerLeft+$bevelamount}] [expr {$bottom-1}] \
+ [expr {$innerRight-$bevelamount}] [expr {$bottom-1}] \
+ [expr {$innerRight-1}] [expr {$bottom-$bevelamount}] \
+ [expr {$outerRight-1}] [expr {$_top + 1}] \
+ -tags $tagList \
+ ]
+ # outline of tab
+ set _gBlackOutline [$canvas create line \
+ $outerLeft [expr {$_top + 1}] \
+ $innerLeft [expr {$bottom -$bevelamount}]\
+ [expr {$innerLeft + $bevelamount}] $bottom \
+ [expr {$innerRight - $bevelamount}] $bottom \
+ $innerRight [expr {$bottom - $bevelamount}]\
+ $outerRight [expr {$_top + 1}] \
+ -tags $tagList \
+ ]
+
+ # top of tab... to make it closed off
+ set _gTopLine [$canvas create line \
+ $outerLeft [expr {$_top + 1}] \
+ $outerRight [expr {$_top + 1}] \
+ -tags $tagList \
+ ]
+
+ # top of tab... to make it closed off
+ set _gTopLineShadow [$canvas create line \
+ $outerLeft $_top \
+ $outerRight $_top \
+ -tags $tagList \
+ ]
+
+ $canvas coords $_gLabel [expr {$innerLeft + $_labelXOrigin}] \
+ [expr {$_top + $_labelYOrigin}]
+
+ if { $image != {} || $bitmap != {} } {
+ $canvas itemconfigure $_gLabel -anchor $anchor
+ } else {
+ $canvas itemconfigure $_gLabel -anchor $anchor -justify $_just
+ }
+ $canvas raise $_gLabel $_gRegion
+
+
+ set _offset [expr {$innerRight - $outerLeft}]
+
+ # width
+ set _majorDim [expr {$outerRight - $outerLeft}]
+
+ # height
+ set _minorDim [expr {$bottom - $_top}]
+
+ set _right $outerRight
+ set _bottom $bottom
+
+ # draw in correct state...
+ if { $_selected } {
+ select
+ } else {
+ deselect
+ }
+}
+
+# ----------------------------------------------------------------------
+# PRIVATE METHOD: _calcLabelDim
+#
+# Calculate the width and height of the label bbox of labelItem
+# can be either text or bitmap (in future also an image)
+#
+# There are two ways to calculate the label bbox.
+#
+# First, if the $_width and/or $_height is specified, we will use
+# it to determine that dimension(s) width and/or height. For
+# a width/height of 0 we use the labels bbox to
+# give us a base width/height.
+# Then we add in the padx/pady to determine final bounds.
+#
+# Uses the following option or option derived variables:
+# -padx ($_padX - converted to pixels)
+# -pady ($_padY - converted to pixels)
+# -anchor ($anchor)
+# -width ($_width) This is the width for inside tab (label area)
+# -height ($_height) This is the width for inside tab (label area)
+#
+# Side Effects:
+# _labelWidth will be set
+# _labelHeight will be set
+# _labelXOrigin will be set
+# _labelYOrigin will be set
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Tab::_calcLabelDim {labelItem} {
+ # ... calculate the label width and height
+ set labelBBox [$_canvas bbox $labelItem]
+
+ if { $_width > 0 } {
+ set _labelWidth [expr {$_width + ($_padX * 2)}]
+ } else {
+ set _labelWidth [expr {
+ ([lindex $labelBBox 2] - [lindex $labelBBox 0]) + ($_padX * 2)}]
+ }
+
+ if { $_height > 0 } {
+ set _labelHeight [expr {$_height + ($_padY * 2)}]
+ } else {
+ set _labelHeight [expr {
+ ([lindex $labelBBox 3] - [lindex $labelBBox 1]) + ($_padY * 2)}]
+ }
+
+ # ... calculate the label anchor point
+ set centerX [expr {$_labelWidth/2.0}]
+ set centerY [expr {$_labelHeight/2.0 - 1}]
+
+ switch $anchor {
+ n {
+ set _labelXOrigin $centerX
+ set _labelYOrigin $_padY
+ set _just center
+ }
+ s {
+ set _labelXOrigin $centerX
+ set _labelYOrigin [expr {$_labelHeight - $_padY}]
+ set _just center
+ }
+ e {
+ set _labelXOrigin [expr {$_labelWidth - $_padX - 1}]
+ set _labelYOrigin $centerY
+ set _just right
+ }
+ w {
+ set _labelXOrigin [expr {$_padX + 2}]
+ set _labelYOrigin $centerY
+ set _just left
+ }
+ c {
+ set _labelXOrigin $centerX
+ set _labelYOrigin $centerY
+ set _just center
+ }
+ ne {
+ set _labelXOrigin [expr {$_labelWidth - $_padX - 1}]
+ set _labelYOrigin $_padY
+ set _just right
+ }
+ nw {
+ set _labelXOrigin [expr {$_padX + 2}]
+ set _labelYOrigin $_padY
+ set _just left
+ }
+ se {
+ set _labelXOrigin [expr {$_labelWidth - $_padX - 1}]
+ set _labelYOrigin [expr {$_labelHeight - $_padY}]
+ set _just right
+ }
+ sw {
+ set _labelXOrigin [expr {$_padX + 2}]
+ set _labelYOrigin [expr {$_labelHeight - $_padY}]
+ set _just left
+ }
+ default {
+ error "bad anchor position: \
+ \"$tabpos\" must be n, ne, nw, s, sw, se, e, w, or center"
+ }
+ }
+}
diff --git a/iwidgets/generic/tclIndex b/iwidgets/generic/tclIndex
new file mode 100644
index 00000000000..f1403ac6b33
--- /dev/null
+++ b/iwidgets/generic/tclIndex
@@ -0,0 +1,1372 @@
+# Tcl autoload index file, version 2.0
+# This file is generated by the "auto_mkindex" command
+# and sourced to set up indexing information for one or
+# more commands. Typically each line is a command that
+# sets an element in the auto_index array, where the
+# element name is the name of a command and the value is
+# a script that loads the command.
+
+set auto_index(::iwidgets::Extbutton) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::extbutton) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::bd) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::bitmap) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::command) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::defaultring) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::defaultringpad) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::image) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::imagepos) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::relief) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::state) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::text) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::constructor) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::flash) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::changeColor) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Extbutton::sink) [list source [file join $dir extbutton.itk]]
+set auto_index(::iwidgets::Buttonbox) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::buttonbox) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::constructor) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::destructor) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::pady) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::padx) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::orient) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::index) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::add) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::insert) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::delete) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::default) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::hide) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::show) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::invoke) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::buttonconfigure) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::buttoncget) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::_getMaxWidth) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::_getMaxHeight) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::_setBoxSize) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Buttonbox::_positionButtons) [list source [file join $dir buttonbox.itk]]
+set auto_index(::iwidgets::Calendar) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::calendar) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::constructor) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::command) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::days) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::backwardimage) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::forwardimage) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::weekdaybackground) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::weekendbackground) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::foreground) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::outline) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::buttonforeground) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::selectcolor) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::selectthickness) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::titlefont) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::datefont) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::currentdatefont) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::dayfont) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::startday) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::get) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::select) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::show) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_drawtext) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_configureHandler) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_change) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_redraw) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_days) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_layout) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_adjustday) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_select) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_selectEvent) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Calendar::_percentSubst) [list source [file join $dir calendar.itk]]
+set auto_index(::iwidgets::Canvasprintbox) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::canvasprintbox) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::printregion) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::output) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::printcmd) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::filename) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::pagesize) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::orient) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::stretch) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::posterize) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::hpagecnt) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::vpagecnt) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::constructor) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::setcanvas) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::getoutput) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::print) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::refresh) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::stop) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::_calc_poster_size) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::_calc_print_region) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::_calc_print_scale) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::_update_canvas) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::_update_attr) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::_mapEventHandler) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::destructor) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintbox::ezPaperInfo) [list source [file join $dir canvasprintbox.itk]]
+set auto_index(::iwidgets::Canvasprintdialog) [list source [file join $dir canvasprintdialog.itk]]
+set auto_index(::iwidgets::canvasprintdialog) [list source [file join $dir canvasprintdialog.itk]]
+set auto_index(::iwidgets::Canvasprintdialog::constructor) [list source [file join $dir canvasprintdialog.itk]]
+set auto_index(::iwidgets::Canvasprintdialog::deactivate) [list source [file join $dir canvasprintdialog.itk]]
+set auto_index(::iwidgets::Canvasprintdialog::getoutput) [list source [file join $dir canvasprintdialog.itk]]
+set auto_index(::iwidgets::Canvasprintdialog::setcanvas) [list source [file join $dir canvasprintdialog.itk]]
+set auto_index(::iwidgets::Canvasprintdialog::refresh) [list source [file join $dir canvasprintdialog.itk]]
+set auto_index(::iwidgets::Canvasprintdialog::print) [list source [file join $dir canvasprintdialog.itk]]
+set auto_index(::iwidgets::Checkbox) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::checkbox) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::constructor) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::orient) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::index) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::add) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::insert) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::delete) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::select) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::toggle) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::get) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::deselect) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::flash) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::buttonconfigure) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Checkbox::gettag) [list source [file join $dir checkbox.itk]]
+set auto_index(::iwidgets::Combobox) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::combobox) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::constructor) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::destructor) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::arrowrelief) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::completion) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::dropdown) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::editable) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::grab) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::listheight) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::margin) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::popupcursor) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::selectioncommand) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::state) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::unique) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::clear) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::curselection) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::delete) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::get) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::getcurselection) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::invoke) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::insert) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::justify) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::see) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::selection) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::size) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::sort) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::xview) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::yview) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_addToList) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_createComponents) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_deleteList) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_deleteText) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_doLayout) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_drawArrow) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_dropdownBtnRelease) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_ignoreNextBtnRelease) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_next) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_packComponents) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_positionList) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_postList) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_previous) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_resizeArrow) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_selectCmd) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_toggleList) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_unpostList) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_commonBindings) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_dropdownBindings) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_simpleBindings) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_listShowing) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_slbListbox) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_stateSelect) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_bs) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Combobox::_lookup) [list source [file join $dir combobox.itk]]
+set auto_index(::iwidgets::Dateentry) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::dateentry) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Dateentry::constructor) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Dateentry::icon) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Dateentry::grab) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Dateentry::state) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Dateentry::_getDefaultIcon) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Dateentry::_popup) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Dateentry::_getPopupDate) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Dateentry::_releaseGrabCheck) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Dateentry::_releaseGrab) [list source [file join $dir dateentry.itk]]
+set auto_index(::iwidgets::Datefield) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::datefield) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::constructor) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::childsitepos) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::command) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::iq) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::get) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::show) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::isvalid) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::_focusIn) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::_keyPress) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::_setField) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::_moveField) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::_whichField) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::_forward) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::_backward) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Datefield::_lastDay) [list source [file join $dir datefield.itk]]
+set auto_index(::iwidgets::Dialog) [list source [file join $dir dialog.itk]]
+set auto_index(::iwidgets::dialog) [list source [file join $dir dialog.itk]]
+set auto_index(::iwidgets::Dialog::constructor) [list source [file join $dir dialog.itk]]
+set auto_index(::iwidgets::Dialogshell) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::dialogshell) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::constructor) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::thickness) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::buttonboxpos) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::separator) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::padx) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::pady) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::childsite) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::index) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::add) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::insert) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::delete) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::hide) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::show) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::default) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::invoke) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::buttonconfigure) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Dialogshell::buttoncget) [list source [file join $dir dialogshell.itk]]
+set auto_index(::iwidgets::Disjointlistbox) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::disjointlistbox) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::constructor) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::listboxClick) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::listboxDblClick) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::transfer) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::getlhs) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::getrhs) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::insertrhs) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::insertlhs) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::clear) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::insert) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::remove) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::showCount) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::setlhs) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::setrhs) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::lhs) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::rhs) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Disjointlistbox::buttonplacement) [list source [file join $dir disjointlistbox.itk]]
+set auto_index(::iwidgets::Entryfield) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::numeric) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::integer) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::alphabetic) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::alphanumeric) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::hexidecimal) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::real) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::entryfield) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::constructor) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::command) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::focuscommand) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::validate) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::invalid) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::pasting) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::fixed) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::childsitepos) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::childsite) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::get) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::delete) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::icursor) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::index) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::insert) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::scan) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::selection) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::xview) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::clear) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::numeric) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::integer) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::alphabetic) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::alphanumeric) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::hexidecimal) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::real) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::_peek) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::_focusCommand) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Entryfield::_keyPress) [list source [file join $dir entryfield.itk]]
+set auto_index(::iwidgets::Extfileselectionbox) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::extfileselectionbox) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::constructor) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::destructor) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::childsitepos) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::fileson) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::dirson) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::selectionon) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::filteron) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::mask) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::directory) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::nomatchstring) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::dirsearchcommand) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::filesearchcommand) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::selectioncommand) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::filtercommand) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::selectdircommand) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::selectfilecommand) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::invalid) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::filetype) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::width) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::height) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::childsite) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::get) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::filter) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_updateLists) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_setFilter) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_setSelection) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_setDirList) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_setFileList) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_selectDir) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_dblSelectDir) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_selectFile) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_selectSelection) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_selectFilter) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_packComponents) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_nPos) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_sPos) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_ePos) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_wPos) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_topPos) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectionbox::_bottomPos) [list source [file join $dir extfileselectionbox.itk]]
+set auto_index(::iwidgets::Extfileselectiondialog) [list source [file join $dir extfileselectiondialog.itk]]
+set auto_index(::iwidgets::extfileselectiondialog) [list source [file join $dir extfileselectiondialog.itk]]
+set auto_index(::iwidgets::Extfileselectiondialog::constructor) [list source [file join $dir extfileselectiondialog.itk]]
+set auto_index(::iwidgets::Extfileselectiondialog::childsite) [list source [file join $dir extfileselectiondialog.itk]]
+set auto_index(::iwidgets::Extfileselectiondialog::get) [list source [file join $dir extfileselectiondialog.itk]]
+set auto_index(::iwidgets::Extfileselectiondialog::filter) [list source [file join $dir extfileselectiondialog.itk]]
+set auto_index(::iwidgets::Extfileselectiondialog::_dbldir) [list source [file join $dir extfileselectiondialog.itk]]
+set auto_index(::iwidgets::Feedback) [list source [file join $dir feedback.itk]]
+set auto_index(::iwidgets::feedback) [list source [file join $dir feedback.itk]]
+set auto_index(::iwidgets::Feedback::constructor) [list source [file join $dir feedback.itk]]
+set auto_index(::iwidgets::Feedback::destructor) [list source [file join $dir feedback.itk]]
+set auto_index(::iwidgets::Feedback::steps) [list source [file join $dir feedback.itk]]
+set auto_index(::iwidgets::Feedback::_display) [list source [file join $dir feedback.itk]]
+set auto_index(::iwidgets::Feedback::reset) [list source [file join $dir feedback.itk]]
+set auto_index(::iwidgets::Feedback::step) [list source [file join $dir feedback.itk]]
+set auto_index(::iwidgets::Fileselectionbox) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::fileselectionbox) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::constructor) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::destructor) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::childsitepos) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::fileson) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::dirson) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::selectionon) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::filteron) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::mask) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::directory) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::nomatchstring) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::dirsearchcommand) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::filesearchcommand) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::selectioncommand) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::filtercommand) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::selectdircommand) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::selectfilecommand) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::invalid) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::filetype) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::width) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::height) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::childsite) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::get) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::filter) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_updateLists) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_setFilter) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_setSelection) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_setDirList) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_setFileList) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_selectDir) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_dblSelectDir) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_selectFile) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_selectSelection) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_selectFilter) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_packComponents) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_nPos) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_sPos) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_ePos) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_wPos) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_topPos) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_centerPos) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectionbox::_bottomPos) [list source [file join $dir fileselectionbox.itk]]
+set auto_index(::iwidgets::Fileselectiondialog) [list source [file join $dir fileselectiondialog.itk]]
+set auto_index(::iwidgets::fileselectiondialog) [list source [file join $dir fileselectiondialog.itk]]
+set auto_index(::iwidgets::Fileselectiondialog::constructor) [list source [file join $dir fileselectiondialog.itk]]
+set auto_index(::iwidgets::Fileselectiondialog::childsite) [list source [file join $dir fileselectiondialog.itk]]
+set auto_index(::iwidgets::Fileselectiondialog::get) [list source [file join $dir fileselectiondialog.itk]]
+set auto_index(::iwidgets::Fileselectiondialog::filter) [list source [file join $dir fileselectiondialog.itk]]
+set auto_index(::iwidgets::Fileselectiondialog::_dbldir) [list source [file join $dir fileselectiondialog.itk]]
+set auto_index(::iwidgets::Finddialog) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::finddialog) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::constructor) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::clearcommand) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::matchcommand) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::patternbackground) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::patternforeground) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::searchforeground) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::searchbackground) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::textwidget) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::clear) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::find) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::_get) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Finddialog::_textExists) [list source [file join $dir finddialog.itk]]
+set auto_index(::iwidgets::Hierarchy) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::hierarchy) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::constructor) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::destructor) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::font) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::selectbackground) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::selectforeground) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::markbackground) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::markforeground) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::querycommand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::selectcommand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::dblclickcommand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::iconcommand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::icondblcommand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::imagecommand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::imagedblcommand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::alwaysquery) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::filter) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::expanded) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::openicon) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::closedicon) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::nodeicon) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::width) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::height) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::visibleitems) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::textmenuloadcommand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::imagemenuloadcommand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::clear) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::selection) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::mark) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::current) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::expand) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::collapse) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::toggle) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::prune) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::draw) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::refresh) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::bbox) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::compare) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::delete) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::dump) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::dlineinfo) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::get) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::index) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::insert) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::scan) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::search) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::see) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::tag) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::window) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::xview) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::yview) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::expanded) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::expState) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_drawLevel) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_contents) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_post) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_imagePost) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_select) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_double) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_iconSelect) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_iconDblSelect) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_imageSelect) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_imageDblClick) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_deselectSubNodes) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_deleteNodeInfo) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_getParent) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_getHeritage) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hierarchy::_isInternalTag) [list source [file join $dir hierarchy.itk]]
+set auto_index(::iwidgets::Hyperhelp) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::hyperhelp) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::constructor) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::topics) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::title) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::helpdir) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::closecmd) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::showtopic) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::followlink) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::forward) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::back) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::updatefeedback) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::_readtopic) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::_fill_go_menu) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::_pageforward) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::_pageback) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::_lineforward) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Hyperhelp::_lineback) [list source [file join $dir hyperhelp.itk]]
+set auto_index(::iwidgets::Labeledframe) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::labeledframe) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::constructor) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::destructor) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::ipadx) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::ipady) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::labelmargin) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::labelpos) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::_initTable) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::childsite) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::_positionLabel) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::_collapseMargin) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledframe::_setMarginThickness) [list source [file join $dir labeledframe.itk]]
+set auto_index(::iwidgets::Labeledwidget) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::alignlabels) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::labeledwidget) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::constructor) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::destructor) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::disabledforeground) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::labelpos) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::labelmargin) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::labeltext) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::labelvariable) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::labelbitmap) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::labelimage) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::state) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::childsite) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::alignlabels) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Labeledwidget::_positionLabel) [list source [file join $dir labeledwidget.itk]]
+set auto_index(::iwidgets::Mainwindow) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::mainwindow) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Mainwindow::constructor) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Mainwindow::helpline) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Mainwindow::statusline) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Mainwindow::childsite) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Mainwindow::menubar) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Mainwindow::toolbar) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Mainwindow::mousebar) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Mainwindow::msgd) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Mainwindow::_exitCB) [list source [file join $dir mainwindow.itk]]
+set auto_index(::iwidgets::Menubar) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::menubar) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::constructor) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::foreground) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::activebackground) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::activeborderwidth) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::activeforeground) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::anchor) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::borderwidth) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::disabledforeground) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::font) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::highlightbackground) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::highlightcolor) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::highlightthickness) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::justify) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::padx) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::pady) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::wraplength) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::menubuttons) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::helpvariable) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::add) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::delete) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::index) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::insert) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::invoke) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::menucget) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::menuconfigure) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::path) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::type) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::yposition) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::menubutton) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::options) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::command) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::checkbutton) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::radiobutton) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::separator) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::cascade) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_addMenuButton) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_insertMenuButton) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_makeMenuButton) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_makeMenu) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_substEvalStr) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_deleteMenu) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_deleteAMenu) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_addEntry) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_addCascade) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_insertEntry) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_insertCascade) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_deleteEntry) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_configureMenu) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_configureMenuOption) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_configureMenuEntry) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_unsetPaths) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_entryPathToTkMenuPath) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_getTkIndex) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_getPdIndex) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_getMenuList) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_getEntryList) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_parsePath) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_getSymbolicPath) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_helpHandler) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::Menubar::_getCallerLevel) [list source [file join $dir menubar.itk]]
+set auto_index(tkMenuFind) [list source [file join $dir menubar.itk]]
+set auto_index(::iwidgets::MsgType) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::messagebox) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox::constructor) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox::destructor) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox::clear) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox::type) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox::issue) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox::save) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox::find) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox::_post) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagebox::export) [list source [file join $dir messagebox.itk]]
+set auto_index(::iwidgets::Messagedialog) [list source [file join $dir messagedialog.itk]]
+set auto_index(::iwidgets::messagedialog) [list source [file join $dir messagedialog.itk]]
+set auto_index(::iwidgets::Messagedialog::constructor) [list source [file join $dir messagedialog.itk]]
+set auto_index(::iwidgets::Messagedialog::imagepos) [list source [file join $dir messagedialog.itk]]
+set auto_index(::iwidgets::Notebook) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::notebook) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::constructor) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::background) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::auto) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::scrollcommand) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::add) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::childsite) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::delete) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::index) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::insert) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::prev) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::next) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::pageconfigure) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::pagecget) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::select) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::view) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::_childSites) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::_scrollCommand) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::_index) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::_createPage) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::_deletePages) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::_configurePages) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Notebook::_tabCommand) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Page) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Page::constructor) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Page::disabledforeground) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Page::label) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Page::command) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Page::childsite) [list source [file join $dir notebook.itk]]
+set auto_index(::iwidgets::Optionmenu) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::optionmenu) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::constructor) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::destructor) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::clicktime) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::command) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::cyclicon) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::width) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::font) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::borderwidth) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::highlightthickness) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::state) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::index) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::delete) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::disable) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::enable) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::get) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::insert) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::select) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::popupMenu) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::sort) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::_buttonRelease) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::_getNextItem) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::_next) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::_previous) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::_postMenu) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::_setItem) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::_setitems) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Optionmenu::_setSize) [list source [file join $dir optionmenu.itk]]
+set auto_index(::iwidgets::Pane) [list source [file join $dir pane.itk]]
+set auto_index(::iwidgets::pane) [list source [file join $dir pane.itk]]
+set auto_index(::iwidgets::Pane::constructor) [list source [file join $dir pane.itk]]
+set auto_index(::iwidgets::Pane::minimum) [list source [file join $dir pane.itk]]
+set auto_index(::iwidgets::Pane::margin) [list source [file join $dir pane.itk]]
+set auto_index(::iwidgets::Pane::childSite) [list source [file join $dir pane.itk]]
+set auto_index(::iwidgets::Panedwindow) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::panedwindow) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::constructor) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::orient) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::sashborderwidth) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::sashcursor) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::sashwidth) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::sashheight) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::thickness) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::sashindent) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::index) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::childsite) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::fraction) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::add) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::insert) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::delete) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::hide) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::show) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::paneconfigure) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::reset) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_pwConfigureEventHandler) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_startGrip) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_endGrip) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_configGrip) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_handleGrip) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_moveSash) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_setFracArray) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_setActivePanes) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_calcFraction) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_makeSashes) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_placeSash) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Panedwindow::_placePanes) [list source [file join $dir panedwindow.itk]]
+set auto_index(::iwidgets::Promptdialog) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::promptdialog) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::constructor) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::get) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::clear) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::insert) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::delete) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::icursor) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::index) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::scan) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::selection) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Promptdialog::xview) [list source [file join $dir promptdialog.itk]]
+set auto_index(::iwidgets::Pushbutton) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::pushbutton) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::constructor) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::destructor) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::padx) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::pady) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::font) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::text) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::bitmap) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::image) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::highlightthickness) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::borderwidth) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::defaultring) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::defaultringpad) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::height) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::width) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::flash) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::invoke) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Pushbutton::_relayout) [list source [file join $dir pushbutton.itk]]
+set auto_index(::iwidgets::Radiobox) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::radiobox) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::constructor) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::command) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::orient) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::index) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::add) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::insert) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::_rearrange) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::delete) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::select) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::get) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::deselect) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::flash) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::buttonconfigure) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::_command) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Radiobox::gettag) [list source [file join $dir radiobox.itk]]
+set auto_index(::iwidgets::Regexpfield) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::regexpfield) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::constructor) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::command) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::focuscommand) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::regexp) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::invalid) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::fixed) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::childsitepos) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::nocase) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::childsite) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::get) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::delete) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::icursor) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::index) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::insert) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::scan) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::selection) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::xview) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::clear) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::_peek) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::_focusCommand) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Regexpfield::_keyPress) [list source [file join $dir regexpfield.itk]]
+set auto_index(::iwidgets::Scrolledcanvas) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::scrolledcanvas) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::constructor) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::destructor) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::autoresize) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::childsite) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::justify) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::addtag) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::bbox) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::bind) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::canvasx) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::canvasy) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::coords) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::create) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::dchars) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::delete) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::dtag) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::find) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::focus) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::gettags) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::icursor) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::index) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::insert) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::itemconfigure) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::itemcget) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::lower) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::move) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::postscript) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::raise) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::scale) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::scan) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::select) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::type) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::xview) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledcanvas::yview) [list source [file join $dir scrolledcanvas.itk]]
+set auto_index(::iwidgets::Scrolledframe) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::scrolledframe) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::Scrolledframe::constructor) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::Scrolledframe::destructor) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::Scrolledframe::childsite) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::Scrolledframe::justify) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::Scrolledframe::xview) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::Scrolledframe::yview) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::Scrolledframe::_configureCanvas) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::Scrolledframe::_configureFrame) [list source [file join $dir scrolledframe.itk]]
+set auto_index(::iwidgets::Scrolledhtml) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::scrolledhtml) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::constructor) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::destructor) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::fontsize) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::fixedfont) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::fontname) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::textbackground) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::linkhighlight) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::unknownimage) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::update) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::clear) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::import) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::render) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_setup) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_definefont) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_append_text) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_set_tag) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_reconfig_tags) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_push) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_pop) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_peek) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_parse_fields) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_href_click) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_set_align) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_fixtablewidth) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_header) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_/header) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_a) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/a) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_address) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/address) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_b) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/b) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_base) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_basefont) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_big) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/big) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_blockquote) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/blockquote) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_body) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/body) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_br) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_center) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/center) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_cite) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/cite) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_code) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/code) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_dir) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/dir) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_div) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_dl) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/dl) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_dt) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_dd) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_dfn) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/dfn) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_em) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/em) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_font) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/font) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_h1) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/h1) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_h2) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/h2) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_h3) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/h3) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_h4) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/h4) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_h5) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/h5) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_h6) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/h6) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_hr) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_i) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/i) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_img) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_kbd) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/kbd) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_li) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_listing) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/listing) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_menu) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/menu) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_ol) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/ol) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_p) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_pre) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/pre) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_samp) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/samp) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_small) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/small) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_sub) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/sub) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_sup) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/sup) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_strong) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/strong) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_table) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/table) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_td) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/td) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_th) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/th) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_title) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/title) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_tr) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/tr) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_tt) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/tt) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_u) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/u) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_ul) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/ul) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_var) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledhtml::_entity_/var) [list source [file join $dir scrolledhtml.itk]]
+set auto_index(::iwidgets::Scrolledlistbox) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::scrolledlistbox) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::constructor) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::destructor) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::dblclickcommand) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::selectioncommand) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::width) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::height) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::visibleitems) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::state) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::curselection) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::activate) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::bbox) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::clear) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::see) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::index) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::_fixIndex) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::delete) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::get) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::getcurselection) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::insert) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::nearest) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::scan) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::selection) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::size) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::selecteditemcount) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::justify) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::sort) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::xview) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::yview) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::itemconfigure) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::_makeSelection) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledlistbox::_dblclick) [list source [file join $dir scrolledlistbox.itk]]
+set auto_index(::iwidgets::Scrolledtext) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::scrolledtext) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::constructor) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::destructor) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::width) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::height) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::visibleitems) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::childsite) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::bbox) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::clear) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::import) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::export) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::compare) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::debug) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::delete) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::dlineinfo) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::get) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::image) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::index) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::insert) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::mark) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::scan) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::search) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::see) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::tag) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::window) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::xview) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledtext::yview) [list source [file join $dir scrolledtext.itk]]
+set auto_index(::iwidgets::Scrolledwidget) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::scrolledwidget) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::constructor) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::destructor) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::sbwidth) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::scrollmargin) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::vscrollmode) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::hscrollmode) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::width) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::height) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::_vertScrollbarDisplay) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::_horizScrollbarDisplay) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::_scrollWidget) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Scrolledwidget::_configureEvent) [list source [file join $dir scrolledwidget.itk]]
+set auto_index(::iwidgets::Selectionbox) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::selectionbox) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::constructor) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::destructor) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::childsitepos) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::margin) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::itemson) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::selectionon) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::width) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::height) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::childsite) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::get) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::curselection) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::clear) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::insert) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::delete) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::size) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::scan) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::nearest) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::index) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::selection) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::selectitem) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectionbox::_packComponents) [list source [file join $dir selectionbox.itk]]
+set auto_index(::iwidgets::Selectiondialog) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::selectiondialog) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::constructor) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::childsite) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::get) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::curselection) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::clear) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::insert) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::delete) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::size) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::scan) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::nearest) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::index) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::selection) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Selectiondialog::selectitem) [list source [file join $dir selectiondialog.itk]]
+set auto_index(::iwidgets::Shell) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::shell) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::constructor) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::master) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::modality) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::padx) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::pady) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::width) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::height) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::childsite) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::activate) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::deactivate) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Shell::center) [list source [file join $dir shell.itk]]
+set auto_index(::iwidgets::Spindate) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::spindate) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::constructor) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::destructor) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::labelpos) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::orient) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::monthon) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::dayon) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::yearon) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::datemargin) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::yeardigits) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::monthformat) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::get) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::show) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::_spinMonth) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::_spinDay) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::_packDate) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spindate::_lastDay) [list source [file join $dir spindate.itk]]
+set auto_index(::iwidgets::Spinint) [list source [file join $dir spinint.itk]]
+set auto_index(::iwidgets::spinint) [list source [file join $dir spinint.itk]]
+set auto_index(::iwidgets::Spinint::constructor) [list source [file join $dir spinint.itk]]
+set auto_index(::iwidgets::Spinint::range) [list source [file join $dir spinint.itk]]
+set auto_index(::iwidgets::Spinint::step) [list source [file join $dir spinint.itk]]
+set auto_index(::iwidgets::Spinint::wrap) [list source [file join $dir spinint.itk]]
+set auto_index(::iwidgets::Spinint::up) [list source [file join $dir spinint.itk]]
+set auto_index(::iwidgets::Spinint::down) [list source [file join $dir spinint.itk]]
+set auto_index(::iwidgets::Spinner) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::spinner) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::constructor) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::destructor) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::arroworient) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::textfont) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::highlightthickness) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::borderwidth) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::increment) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::decrement) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::repeatinterval) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::repeatdelay) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::foreground) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::up) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::down) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::_positionArrows) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::_pushup) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::_pushdown) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::_doup) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::_dodown) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::_relup) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::_reldown) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::_up) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spinner::_down) [list source [file join $dir spinner.itk]]
+set auto_index(::iwidgets::Spintime) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::spintime) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::constructor) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::destructor) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::orient) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::labelpos) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::houron) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::minuteon) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::secondon) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::timemargin) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::militaryon) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::get) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::show) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::_packTime) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Spintime::_down60) [list source [file join $dir spintime.itk]]
+set auto_index(::iwidgets::Tabnotebook) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::constructor) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::tabnotebook) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::destructor) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::borderwidth) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::state) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::disabledforeground) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::scrollcommand) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::equaltabs) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::font) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::width) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::height) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::foreground) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::background) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::tabforeground) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::tabbackground) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::backdrop) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::margin) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::tabborders) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::bevelamount) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::raiseselect) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::auto) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::start) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::padx) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::pady) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::gap) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::angle) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::tabpos) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::configure) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::add) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::childsite) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::delete) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::index) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::insert) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::prev) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::next) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::pageconfigure) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::select) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::view) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::_getArgs) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::_reconfigureTabset) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::_canvasReconfigure) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::_redrawBorder) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::_recomputeBorder) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::_pageReconfigure) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::_pack) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabnotebook::_resize) [list source [file join $dir tabnotebook.itk]]
+set auto_index(::iwidgets::Tabset) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::tabset) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::constructor) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::destructor) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::width) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::equaltabs) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::height) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::tabpos) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::raiseselect) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::start) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::margin) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::tabborders) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::bevelamount) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::padx) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::pady) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::gap) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::angle) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::font) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::state) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::disabledforeground) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::foreground) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::background) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::selectforeground) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::backdrop) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::selectbackground) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::command) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::add) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::configure) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_configRelayout) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::delete) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::index) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::insert) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::prev) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::next) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::select) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::tabcget) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::tabconfigure) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_selectName) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_createTab) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_deleteTabs) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_index) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_tabConfigure) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_relayoutTabs) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_drawBevelBorder) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_calcNextTabOffset) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_tabBounds) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_recalcCanvasGeom) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_canvasReconfigure) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_startMove) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_moveTabs) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tabset::_endMove) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::constructor) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::destructor) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::bevelamount) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::state) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::height) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::width) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::anchor) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::left) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::top) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::image) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::bitmap) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::label) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::padx) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::pady) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::selectbackground) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::selectforeground) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::disabledforeground) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::background) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::foreground) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::orient) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::invert) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::angle) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::font) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::tabborders) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::configure) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::bbox) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::deselect) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::lower) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::majordim) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::minordim) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::offset) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::raise) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::select) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::labelheight) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::labelwidth) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::_selectNoRaise) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::_deselectNoLower) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::_makeTab) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::_createLabel) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::_makeEastTab) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::_makeWestTab) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::_makeNorthTab) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::_makeSouthTab) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Tab::_calcLabelDim) [list source [file join $dir tabset.itk]]
+set auto_index(::iwidgets::Timeentry) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::timeentry) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::Timeentry::constructor) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::Timeentry::icon) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::Timeentry::grab) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::Timeentry::state) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::Timeentry::_getDefaultIcon) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::Timeentry::_popup) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::Timeentry::_getPopupTime) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::Timeentry::_releaseGrab) [list source [file join $dir timeentry.itk]]
+set auto_index(::iwidgets::Timefield) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::timefield) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::constructor) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::childsitepos) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::command) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::iq) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::format) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::gmt) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::state) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::get) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::show) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::isvalid) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_focusIn) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_keyPress) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_toggleAmPm) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_setField) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_moveField) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_whichField) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_forwardCivilian) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_forwardMilitary) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_backwardCivilian) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Timefield::_backwardMilitary) [list source [file join $dir timefield.itk]]
+set auto_index(::iwidgets::Toolbar) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::constructor) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::toolbar) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::destructor) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::balloonbackground) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::balloonforeground) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::balloonfont) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::orient) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::add) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::delete) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::index) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::insert) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::itemcget) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::itemconfigure) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::_resetBalloonTimer) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::_startBalloonDelay) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::_stopBalloonDelay) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::_addWidget) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::_deleteWidgets) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::_index) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::hideHelp) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::showHelp) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::showBalloon) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::hideBalloon) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::_getAttachedOption) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::_setAttachedOption) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Toolbar::_packToolbar) [list source [file join $dir toolbar.itk]]
+set auto_index(::iwidgets::Watch) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::watch) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::constructor) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::destructor) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::_handReleaseCB) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::_handMotionCB) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::get) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::watch) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::_drawHand) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::show) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::_displayClock) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::state) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::showampm) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::pivotcolor) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::clockstipple) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::clockcolor) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::hourcolor) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::minutecolor) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::secondcolor) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::tickcolor) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::hourradius) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::minuteradius) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::Watch::secondradius) [list source [file join $dir watch.itk]]
+set auto_index(::iwidgets::colors::rgbToNumeric) [list source [file join $dir colors.itcl]]
+set auto_index(::iwidgets::colors::rgbToHsb) [list source [file join $dir colors.itcl]]
+set auto_index(::iwidgets::colors::hsbToRgb) [list source [file join $dir colors.itcl]]
+set auto_index(::iwidgets::colors::topShadow) [list source [file join $dir colors.itcl]]
+set auto_index(::iwidgets::colors::bottomShadow) [list source [file join $dir colors.itcl]]
+set auto_index(::iwidgets::roman2) [list source [file join $dir roman.itcl]]
+set auto_index(::iwidgets::roman) [list source [file join $dir roman.itcl]]
+set auto_index(::iwidgets::Scopedobject) [list source [file join $dir scopedobject.itcl]]
+set auto_index(::iwidgets::scopedobject) [list source [file join $dir scopedobject.itcl]]
+set auto_index(::iwidgets::Scopedobject::constructor) [list source [file join $dir scopedobject.itcl]]
+set auto_index(::iwidgets::Scopedobject::destructor) [list source [file join $dir scopedobject.itcl]]
+set auto_index(::iwidgets::Scopedobject::_traceCommand) [list source [file join $dir scopedobject.itcl]]
+set auto_index(::iwidgets::Scopedobject::enterscopecommand) [list source [file join $dir scopedobject.itcl]]
+set auto_index(::iwidgets::Scopedobject::exitscopecommand) [list source [file join $dir scopedobject.itcl]]
diff --git a/iwidgets/generic/timeentry.itk b/iwidgets/generic/timeentry.itk
new file mode 100644
index 00000000000..58a19ae090a
--- /dev/null
+++ b/iwidgets/generic/timeentry.itk
@@ -0,0 +1,398 @@
+#
+# Timeentry
+# ----------------------------------------------------------------------
+# Implements a quicken style time entry field with a popup clock
+# by combining the timefield and watch widgets together. This
+# allows a user to enter the time via the keyboard or by using the
+# mouse by selecting the watch icon which brings up a popup clock.
+# ----------------------------------------------------------------------
+# AUTHOR: Mark L. Ulferts E-mail: mulferts@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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, UPTIMES, 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 Timeentry {
+ keep -background -borderwidth -cursor -foreground -highlightcolor \
+ -highlightthickness -labelfont -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# TIMEENTRY
+# ------------------------------------------------------------------
+itcl::class iwidgets::Timeentry {
+ inherit iwidgets::Timefield
+
+ constructor {args} {}
+
+ itk_option define -grab grab Grab "global"
+ itk_option define -icon icon Icon {}
+ itk_option define -state state State normal
+ itk_option define -closetext closeText Text Close
+
+ #
+ # The watch widget isn't created until needed, yet we need
+ # its options to be available upon creation of a timeentry widget.
+ # So, we'll define them in these class now so they can just be
+ # propagated onto the watch later.
+ #
+ itk_option define -hourradius hourRadius Radius .50
+ itk_option define -hourcolor hourColor Color red
+
+ itk_option define -minuteradius minuteRadius Radius .80
+ itk_option define -minutecolor minuteColor Color yellow
+
+ itk_option define -pivotradius pivotRadius Radius .10
+ itk_option define -pivotcolor pivotColor Color white
+
+ itk_option define -secondradius secondRadius Radius .90
+ itk_option define -secondcolor secondColor Color black
+
+ itk_option define -clockcolor clockColor Color white
+ itk_option define -clockstipple clockStipple ClockStipple {}
+
+ itk_option define -tickcolor tickColor Color black
+
+ itk_option define -watchheight watchHeight Height 175
+ itk_option define -watchwidth watchWidth Width 155
+
+ protected {
+ method _getPopupTime {}
+ method _releaseGrab {}
+ method _popup {}
+ method _getDefaultIcon {}
+
+ common _defaultIcon ""
+ }
+}
+
+#
+# Provide a lowercased access method for the timeentry class.
+#
+proc ::iwidgets::timeentry {pathName args} {
+ uplevel ::iwidgets::Timeentry $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Timeentry.watchWidth 155 widgetDefault
+option add *Timeentry.watchHeight 175 widgetDefault
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::constructor {args} {
+ #
+ # Create an icon label to act as a button to bring up the
+ # watch popup.
+ #
+ itk_component add iconbutton {
+ label $itk_interior.iconbutton -relief raised
+ } {
+ keep -borderwidth -cursor -foreground
+ }
+ grid $itk_component(iconbutton) -row 0 -column 0 -sticky ns
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -icon
+#
+# Specifies the clock icon image to be used in the time entry.
+# Should one not be provided, then a default pixmap will be used
+# if possible, bitmap otherwise.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timeentry::icon {
+ if {$itk_option(-icon) == {}} {
+ $itk_component(iconbutton) configure -image [_getDefaultIcon]
+ } else {
+ if {[lsearch [image names] $itk_option(-icon)] == -1} {
+ error "bad icon option \"$itk_option(-icon)\":\
+ should be an existing image"
+ } else {
+ $itk_component(iconbutton) configure -image $itk_option(-icon)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -grab
+#
+# Specifies the grab level, local or global, to be obtained when
+# bringing up the popup watch. The default is global.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timeentry::grab {
+ switch -- $itk_option(-grab) {
+ "local" - "global" {}
+ default {
+ error "bad grab option \"$itk_option(-grab)\":\
+ should be local or global"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -state
+#
+# Specifies the state of the widget which may be disabled or
+# normal. A disabled state prevents selection of the time field
+# or time icon button.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timeentry::state {
+ switch -- $itk_option(-state) {
+ normal {
+ bind $itk_component(iconbutton) <Button-1> [itcl::code $this _popup]
+ }
+ disabled {
+ bind $itk_component(iconbutton) <Button-1> {}
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _getDefaultIcon
+#
+# This method is invoked uto retrieve the name of the default icon
+# image displayed in the icon button.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::_getDefaultIcon {} {
+
+ if {[lsearch [image types] pixmap] != -1} {
+ set _defaultIcon [image create pixmap -data {
+ /* XPM */
+ static char *watch1a[] = {
+ /* width height num_colors chars_per_pixel */
+ " 20 20 8 1",
+ /* colors */
+ ". c #000000",
+ "# c #000099",
+ "a c #009999",
+ "b c #999999",
+ "c c #cccccc",
+ "d c #ffff00",
+ "e c #d9d9d9",
+ "f c #ffffff",
+ /* pixels */
+ "eeeeebbbcccccbbbeeee",
+ "eeeee...#####..beeee",
+ "eeeee#aacccccaabeeee",
+ "eeee#accccccccc##eee",
+ "eee#ccc#cc#ccdcff#ee",
+ "ee#accccccccccfcca#e",
+ "eeaccccccc.cccfcccae",
+ "eeac#cccfc.cccc##cae",
+ "e#cccccffc.cccccccc#",
+ "e#ccccfffc.cccccccc#",
+ "e#cc#ffcc......c#cc#",
+ "e#ccfffccc.cccccccc#",
+ "e#cffccfcc.cccccccc#",
+ "eeafdccfcccccccd#cae",
+ "eeafcffcccccccccccae",
+ "eee#fcc#cccccdccc#ee",
+ "eee#fcc#cc#cc#ccc#ee",
+ "eeee#accccccccc##eee",
+ "eeeee#aacccccaabeeee",
+ "eeeee...#####..beeee"
+ };
+ }]
+ } else {
+ set _defaultIcon [image create bitmap -data {
+ #define watch1a_width 20
+ #define watch1a_height 20
+ static char watch1a_bits[] = {
+ 0x40,0x40,0xf0,0xe0,0x7f,0xf0,0xe0,0xe0,0xf0,0x30,
+ 0x80,0xf1,0x88,0x04,0xf2,0x0c,0x00,0xf6,0x04,0x04,
+ 0xf4,0x94,0x84,0xf5,0x02,0x06,0xf8,0x02,0x0c,0xf8,
+ 0x12,0x7e,0xf9,0x02,0x04,0xf8,0x02,0x24,0xf8,0x04,
+ 0x00,0xf5,0x04,0x00,0xf4,0x88,0x02,0xf2,0x88,0x64,
+ 0xf2,0x30,0x80,0xf1,0xe0,0x60,0xf0,0xe0,0xff,0xf0};
+ }]
+ }
+
+ #
+ # Since this image will only need to be created once, we redefine
+ # this method to just return the image name for subsequent calls.
+ #
+ itcl::body ::iwidgets::Timeentry::_getDefaultIcon {} {
+ return $_defaultIcon
+ }
+
+ return $_defaultIcon
+}
+
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _popup
+#
+# This method is invoked upon selection of the icon button. It
+# creates a watch widget within a toplevel popup, calculates
+# the position at which to display the watch, performs a grab
+# and displays the watch.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::_popup {} {
+ #
+ # First, let's nullify the icon binding so that any another
+ # selections are ignored until were done with this one. Next,
+ # change the relief of the icon.
+ #
+ bind $itk_component(iconbutton) <Button-1> {}
+ $itk_component(iconbutton) configure -relief sunken
+
+ #
+ # Create a withdrawn toplevel widget and remove the window
+ # decoration via override redirect.
+ #
+ itk_component add -private popup {
+ toplevel $itk_interior.popup
+ }
+ $itk_component(popup) configure -borderwidth 2 -background black
+ wm withdraw $itk_component(popup)
+ wm overrideredirect $itk_component(popup) 1
+
+ #
+ # Add a binding to for Escape to always release the grab.
+ #
+ bind $itk_component(popup) <KeyPress-Escape> [itcl::code $this _releaseGrab]
+
+ #
+ # Create the watch widget.
+ #
+ itk_component add watch {
+ iwidgets::Watch $itk_component(popup).watch
+ } {
+ usual
+
+ rename -width -watchwidth watchWidth Width
+ rename -height -watchheight watchHeight Height
+
+ keep -hourradius -minuteradius -minutecolor -pivotradius -pivotcolor \
+ -secondradius -secondcolor -clockcolor -clockstipple -tickcolor
+ }
+ grid $itk_component(watch) -row 0 -column 0
+ $itk_component(watch) configure -cursor top_left_arrow
+
+ #
+ # Create a button widget so the user can say they are done.
+ #
+ itk_component add close {
+ button $itk_component(popup).close -command [itcl::code $this _getPopupTime]
+ } {
+ usual
+ rename -text -closetext closeText Text
+ }
+ grid $itk_component(close) -row 1 -column 0 -sticky ew
+ $itk_component(close) configure -cursor top_left_arrow
+
+ #
+ # The icon button will be used as the basis for the position of the
+ # popup on the screen. We'll always attempt to locate the popup
+ # off the lower right corner of the button. If that would put
+ # the popup off the screen, then we'll put above the upper left.
+ #
+ set rootx [winfo rootx $itk_component(iconbutton)]
+ set rooty [winfo rooty $itk_component(iconbutton)]
+ set popupwidth [cget -watchwidth]
+ set popupheight [expr {[cget -watchheight] + \
+ [winfo reqheight $itk_component(close)]}]
+
+ set popupx [expr {$rootx + 3 + \
+ [winfo width $itk_component(iconbutton)]}]
+ set popupy [expr {$rooty + 3 + \
+ [winfo height $itk_component(iconbutton)]}]
+
+ if {(($popupx + $popupwidth) > [winfo screenwidth .]) || \
+ (($popupy + $popupheight) > [winfo screenheight .])} {
+ set popupx [expr {$rootx - 3 - $popupwidth}]
+ set popupy [expr {$rooty - 3 - $popupheight}]
+ }
+
+ #
+ # Get the current time from the timefield widget and both
+ # show and select it on the watch.
+ #
+ $itk_component(watch) show [get]
+
+ #
+ # Display the popup at the calculated position.
+ #
+ wm geometry $itk_component(popup) +$popupx+$popupy
+ wm deiconify $itk_component(popup)
+ tkwait visibility $itk_component(popup)
+
+ #
+ # Perform either a local or global grab based on the -grab option.
+ #
+ if {$itk_option(-grab) == "local"} {
+ grab $itk_component(popup)
+ } else {
+ grab -global $itk_component(popup)
+ }
+
+ #
+ # Make sure the widget is above all others and give it focus.
+ #
+ raise $itk_component(popup)
+ focus $itk_component(watch)
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _popupGetTime
+#
+# This method is the callback for selection of a time on the
+# watch. It releases the grab and sets the time in the
+# timefield widget.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::_getPopupTime {} {
+ show [$itk_component(watch) get -clicks]
+ _releaseGrab
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _releaseGrab
+#
+# This method releases the grab, destroys the popup, changes the
+# relief of the button back to raised and reapplies the binding
+# to the icon button that engages the popup action.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timeentry::_releaseGrab {} {
+ grab release $itk_component(popup)
+ $itk_component(iconbutton) configure -relief raised
+ destroy $itk_component(popup)
+ bind $itk_component(iconbutton) <Button-1> [itcl::code $this _popup]
+}
diff --git a/iwidgets/generic/timefield.itk b/iwidgets/generic/timefield.itk
new file mode 100644
index 00000000000..ee99e383059
--- /dev/null
+++ b/iwidgets/generic/timefield.itk
@@ -0,0 +1,1018 @@
+#
+# Timefield
+# ----------------------------------------------------------------------
+# Implements a time entry field with adjustable built-in intelligence
+# levels.
+# ----------------------------------------------------------------------
+# AUTHOR: John A. Tucker E-mail: jatucker@austin.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# Copyright (c) 1997 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.
+# ======================================================================
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Timefield.justify center widgetDefault
+
+
+#
+# Usual options.
+#
+itk::usual Timefield {
+ keep -background -borderwidth -cursor -foreground -highlightcolor \
+ -highlightthickness -labelfont -textbackground -textfont
+}
+
+# ------------------------------------------------------------------
+# TIMEFIELD
+# ------------------------------------------------------------------
+itcl::class iwidgets::Timefield {
+
+ inherit iwidgets::Labeledwidget
+
+ constructor {args} {}
+
+ itk_option define -childsitepos childSitePos Position e
+ itk_option define -command command Command {}
+ itk_option define -seconds seconds Seconds on
+ itk_option define -format format Format civilian
+ itk_option define -iq iq Iq high
+ itk_option define -gmt gmt GMT no
+ itk_option define -state state State normal
+
+ public {
+ method get {{format "-string"}}
+ method isvalid {}
+ method show {{time "now"}}
+ }
+
+ protected {
+ method _backwardCivilian {}
+ method _backwardMilitary {}
+ method _focusIn {}
+ method _forwardCivilian {}
+ method _forwardMilitary {}
+ method _keyPress {char sym state}
+ method _moveField {direction}
+ method _setField {field}
+ method _whichField {}
+ method _toggleAmPm {}
+
+ variable _cfield hour
+ variable _formatString "%r"
+ variable _fields {}
+ variable _numFields 4
+ variable _forward {}
+ variable _backward {}
+ variable _timeVar ""
+
+ common _militaryFields {hour minute second}
+ common _civilianFields {hour minute second ampm}
+ }
+}
+
+#
+# Provide a lowercased access method for the timefield class.
+#
+proc iwidgets::timefield {pathName args} {
+ uplevel iwidgets::Timefield $pathName $args
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::constructor {args} {
+ component hull configure -borderwidth 0
+
+ #
+ # Create an entry field for entering the time.
+ #
+ itk_component add time {
+ entry $itk_interior.time
+ } {
+ keep -borderwidth -cursor -exportselection \
+ -foreground -highlightcolor -highlightthickness \
+ -insertbackground -justify -relief -textvariable
+
+ rename -font -textfont textFont Font
+ rename -highlightbackground -background background Background
+ rename -background -textbackground textBackground Background
+ }
+
+ #
+ # Create the child site widget.
+ #
+ itk_component add -protected dfchildsite {
+ frame $itk_interior.dfchildsite
+ }
+ set itk_interior $itk_component(dfchildsite)
+
+ #
+ # Add timefield event bindings for focus in and keypress events.
+ #
+ bind $itk_component(time) <FocusIn> [itcl::code $this _focusIn]
+ bind $itk_component(time) <KeyPress> [itcl::code $this _keyPress %A %K %s]
+ bind $itk_component(time) <1> "focus $itk_component(time); break"
+
+ #
+ # Disable some mouse button event bindings:
+ # Button Motion
+ # Double-Clicks
+ # Triple-Clicks
+ # Button2
+ #
+ bind $itk_component(time) <Button1-Motion> break
+ bind $itk_component(time) <Button2-Motion> break
+ bind $itk_component(time) <Double-Button> break
+ bind $itk_component(time) <Triple-Button> break
+ bind $itk_component(time) <2> break
+
+ #
+ # Initialize the widget based on the command line options.
+ #
+ eval itk_initialize $args
+
+ #
+ # Initialize the time to the current time.
+ #
+ show
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: -childsitepos
+#
+# Specifies the position of the child site in the widget. Valid
+# locations are n, s, e, and w.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timefield::childsitepos {
+ set parent [winfo parent $itk_component(time)]
+
+ switch $itk_option(-childsitepos) {
+ n {
+ grid $itk_component(dfchildsite) -row 0 -column 0 -sticky ew
+ grid $itk_component(time) -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(dfchildsite) -row 0 -column 1 -sticky ns
+ grid $itk_component(time) -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(dfchildsite) -row 1 -column 0 -sticky ew
+ grid $itk_component(time) -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(dfchildsite) -row 0 -column 0 -sticky ns
+ grid $itk_component(time) -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: -command
+#
+# Command invoked upon detection of return key press event.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timefield::command {}
+
+# ------------------------------------------------------------------
+# OPTION: -iq
+#
+# Specifies the level of intelligence to be shown in the actions
+# taken by the time field during the processing of keypress events.
+# Valid settings include high or low. With a high iq,
+# the time prevents the user from typing in an invalid time. For
+# example, if the current time is 05/31/1997 and the user changes
+# the hour to 04, then the minute will be instantly modified for them
+# to be 30. In addition, leap seconds are fully taken into account.
+# A setting of low iq instructs the widget to do no validity checking
+# at all during time entry. With a low iq level, it is assumed that
+# the validity will be determined at a later time using the time's
+# isvalid command.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timefield::iq {
+
+ switch $itk_option(-iq) {
+ high - low {
+
+ }
+ default {
+ error "bad iq option \"$itk_option(-iq)\": should be high or low"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -format
+#
+# Specifies the time format displayed in the entry widget.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timefield::format {
+
+ switch $itk_option(-format) {
+ civilian {
+ set _backward _backwardCivilian
+ set _forward _forwardCivilian
+ set _fields $_civilianFields
+ set _numFields 4
+ set _formatString "%r"
+ $itk_component(time) config -width 11
+ }
+ military {
+ set _backward _backwardMilitary
+ set _forward _forwardMilitary
+ set _fields $_militaryFields
+ set _numFields 3
+ set _formatString "%T"
+ $itk_component(time) config -width 8
+ }
+ default {
+ error "bad iq option \"$itk_option(-iq)\":\
+ should be civilian or military"
+ }
+ }
+
+ #
+ # Update the current contents of the entry field to reflect
+ # the configured format.
+ #
+ show $_timeVar
+}
+
+# ------------------------------------------------------------------
+# OPTION: -gmt
+#
+# This option is used for GMT time. Must be a boolean value.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timefield::gmt {
+ switch $itk_option(-gmt) {
+ 0 - no - false - off { }
+ 1 - yes - true - on { }
+ default {
+ error "bad gmt option \"$itk_option(-gmt)\": should be boolean"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -state
+#
+# Disable the
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Timefield::state {
+ switch -- $itk_option(-state) {
+ normal {
+ $itk_component(time) configure -state normal
+ }
+ disabled {
+ focus $itk_component(hull)
+ $itk_component(time) configure -state disabled
+ }
+ default {
+ error "Invalid value for -state: $itk_option(-state). Should be\
+ \"normal\" or \"disabled\"."
+ }
+ }
+}
+
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: get ?format?
+#
+# Return the current contents of the timefield in one of two formats
+# string or as an integer clock value using the -string and -clicks
+# options respectively. The default is by string. Reference the
+# clock command for more information on obtaining times and their
+# formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::get {{format "-string"}} {
+ set _timeVar [$itk_component(time) get]
+
+ switch -- $format {
+ "-string" {
+ return $_timeVar
+ }
+ "-clicks" {
+ return [::clock scan $_timeVar -gmt $itk_option(-gmt)]
+ }
+ default {
+ error "bad format option \"$format\":\
+ should be -string or -clicks"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: show time
+#
+# Changes the currently displayed time to be that of the time
+# argument. The time may be specified either as a string or an
+# integer clock value. Reference the clock command for more
+# information on obtaining times and their formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::show {{time "now"}} {
+ set icursor [$itk_component(time) index insert]
+
+ if {$time == {}} {
+ set time "now"
+ }
+
+ switch -regexp -- $time {
+
+ {^now$} {
+ set seconds [::clock seconds]
+ }
+
+ {^[0-9]+$} {
+ if { [catch {::clock format $time -gmt $itk_option(-gmt)}] } {
+ error "bad time: \"$time\", must be a valid time \
+ string, clock clicks value or the keyword now"
+ }
+ set seconds $time
+ }
+
+ default {
+ if {[catch {set seconds [::clock scan $time -gmt $itk_option(-gmt)]}]} {
+ error "bad time: \"$time\", must be a valid time \
+ string, clock clicks value or the keyword now"
+ }
+ }
+ }
+
+ set _timeVar [::clock format $seconds -format $_formatString \
+ -gmt $itk_option(-gmt)]
+
+ $itk_component(time) delete 0 end
+ $itk_component(time) insert end $_timeVar
+ $itk_component(time) icursor $icursor
+
+ return $_timeVar
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: isvalid
+#
+# Returns a boolean indication of the validity of the currently
+# displayed time value. For example, 09:59::59 is valid whereas
+# 26:59:59 is invalid.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::isvalid {} {
+ set _timeVar [$itk_component(time) get]
+ return [expr {([catch {::clock scan $_timeVar -gmt $itk_option(-gmt)}] == 0)}]
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _focusIn
+#
+# This method is bound to the <FocusIn> event. It resets the
+# insert cursor and field settings to be back to their last known
+# positions.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_focusIn {} {
+ _setField $_cfield
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _keyPress
+#
+# This method is the workhorse of the class. It is bound to the
+# <KeyPress> event and controls the processing of all key strokes.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_keyPress {char sym state} {
+
+ #
+ # Determine which field we are in currently. This is needed
+ # since the user may have moved to this position via a mouse
+ # selection and so it would not be in the position we last
+ # knew it to be.
+ #
+ set _cfield [_whichField ]
+
+ #
+ # Set up a few basic variables we'll be needing throughout the
+ # rest of the method such as the position of the insert cursor
+ # and the currently displayed minute, hour, and second.
+ #
+ set inValid 0
+ set icursor [$itk_component(time) index insert]
+ set lastField [lindex $_fields end]
+
+ set prevtime $_timeVar
+ regexp {^([0-9])([0-9]):([0-9])([0-9]):([0-9])([0-9]).*$} \
+ $_timeVar dummy \
+ hour1 hour2 minute1 minute2 second1 second2
+ set hour "$hour1$hour2"
+ set minute "$minute1$minute2"
+ set second "$second1$second2"
+
+ #
+ # Process numeric keystrokes. This involes a fair amount of
+ # processing with step one being to check and make sure we
+ # aren't attempting to insert more that 6 characters. If
+ # so ring the bell and break.
+ #
+ if {![catch {expr {int($char)}}]} {
+
+ # If we are currently in the hour field then we process the
+ # number entered based on the cursor position. If we are at
+ # at the first position and our iq is low, then accept any
+ # input.
+ #
+ # if the current format is military, then
+ # validate the hour field which can be [00 - 23]
+ #
+ switch $_cfield {
+ hour {
+ if {$itk_option(-iq) == "low"} {
+ $itk_component(time) delete $icursor
+ $itk_component(time) insert $icursor $char
+
+ } elseif {$itk_option(-format) == "military"} {
+ if {$icursor == 0} {
+ #
+ # if the digit is less than 2, then
+ # the second hour digit is valid for 0-9
+ #
+ if {$char < 2} {
+ $itk_component(time) delete 0 1
+ $itk_component(time) insert 0 $char
+
+ #
+ # if the digit is equal to 2, then
+ # the second hour digit is valid for 0-3
+ #
+ } elseif {$char == 2} {
+ $itk_component(time) delete 0 1
+ $itk_component(time) insert 0 $char
+
+ if {$hour2 > 3} {
+ $itk_component(time) delete 1 2
+ $itk_component(time) insert 1 "0"
+ $itk_component(time) icursor 1
+ }
+
+ #
+ # if the digit is greater than 2, then
+ # set the first hour digit to 0 and the
+ # second hour digit to the value.
+ #
+ } elseif {$char > 2} {
+ $itk_component(time) delete 0 2
+ $itk_component(time) insert 0 "0$char"
+ set icursor 1
+ } else {
+ set inValid 1
+ }
+
+ #
+ # if the insertion cursor is for the second hour digit, then
+ # format is military, then it can only be valid if the first
+ # hour digit is less than 2 or the new digit is less than 4
+ #
+ } else {
+ if {$hour1 < 2 || $char < 4} {
+ $itk_component(time) delete 1 2
+ $itk_component(time) insert 1 $char
+ } else {
+ set inValid 1
+ }
+ }
+
+ #
+ # The format is civilian, so we need to
+ # validate the hour field which can be [01 - 12]
+ #
+ } else {
+ if {$icursor == 0} {
+ #
+ # if the digit is 0, then
+ # the second hour digit is valid for 1-9
+ # so just insert it.
+ #
+ if {$char == 0 && $hour2 != 0} {
+ $itk_component(time) delete 0 1
+ $itk_component(time) insert 0 $char
+
+ #
+ # if the digit is equal to 1, then
+ # the second hour digit is valid for 0-2
+ #
+ } elseif {$char == 1} {
+ $itk_component(time) delete 0 1
+ $itk_component(time) insert 0 $char
+
+ if {$hour2 > 2} {
+ $itk_component(time) delete 1 2
+ $itk_component(time) insert 1 0
+ set icursor 1
+ }
+
+ #
+ # if the digit is greater than 1, then
+ # set the first hour digit to 0 and the
+ # second hour digit to the value.
+ #
+ } elseif {$char > 1} {
+ $itk_component(time) delete 0 2
+ $itk_component(time) insert 0 "0$char"
+ set icursor 1
+
+ } else {
+ set inValid 1
+ }
+
+ #
+ # The insertion cursor is at the second hour digit, so
+ # it can only be valid if the firs thour digit is 0
+ # or the new digit is less than or equal to 2
+ #
+ } else {
+ if {$hour1 == 0 || $char <= 2} {
+ $itk_component(time) delete 1 2
+ $itk_component(time) insert 1 $char
+ } else {
+ set inValid 1
+ }
+ }
+ }
+
+ if {$inValid} {
+ bell
+ } elseif {$icursor == 1} {
+ _setField minute
+ }
+ }
+
+ minute {
+ if {$itk_option(-iq) == "low" || $char < 6 || $icursor == 4} {
+ $itk_component(time) delete $icursor
+ $itk_component(time) insert $icursor $char
+ } elseif {$itk_option(-iq) == "high"} {
+ if {$char > 5} {
+ $itk_component(time) delete 3 5
+ $itk_component(time) insert 3 "0$char"
+ set icursor 4
+ }
+ }
+
+ if {$icursor == 4} {
+ _setField second
+ }
+ }
+
+ second {
+ if {$itk_option(-iq) == "low" || $char < 6 || $icursor == 7} {
+ $itk_component(time) delete $icursor
+ $itk_component(time) insert $icursor $char
+
+ } elseif {$itk_option(-iq) == "high"} {
+ if {$char > 5} {
+ $itk_component(time) delete 6 8
+ $itk_component(time) insert 6 "0$char"
+ set icursor 7
+ }
+ }
+
+ if {$icursor == 7} {
+ _moveField forward
+ }
+ }
+ }
+
+ set _timeVar [$itk_component(time) get]
+ return -code break
+ }
+
+ #
+ # Process the plus and the up arrow keys. They both yield the same
+ # effect, they increment the minute by one.
+ #
+ switch $sym {
+ p - P {
+ if {$itk_option(-format) == "civilian"} {
+ $itk_component(time) delete 9 10
+ $itk_component(time) insert 9 P
+ _setField hour
+ }
+ }
+
+ a - A {
+ if {$itk_option(-format) == "civilian"} {
+ $itk_component(time) delete 9 10
+ $itk_component(time) insert 9 A
+ _setField hour
+ }
+ }
+
+ plus - Up {
+ if {$_cfield == "ampm"} {
+ _toggleAmPm
+ } else {
+ set newclicks [::clock scan "$prevtime 1 $_cfield"]
+ show [::clock format $newclicks -format $_formatString]
+ }
+ }
+
+ minus - Down {
+ #
+ # Process the minus and the down arrow keys which decrement the value
+ # of the field in which the cursor is currently positioned.
+ #
+ if {$_cfield == "ampm"} {
+ _toggleAmPm
+ } else {
+ set newclicks [::clock scan "$prevtime 1 $_cfield ago"]
+ show [::clock format $newclicks -format $_formatString]
+ }
+ }
+
+ Tab {
+ #
+ # A tab key moves the "hour:minute:second" field forward by one unless
+ # the current field is the second. In that case we'll let tab
+ # do what is supposed to and pass the focus onto the next widget.
+ #
+ if {$state == 0} {
+
+ if {($itk_option(-format) == "civilian" && $_cfield == $lastField)} {
+ _setField hour
+ return -code continue
+ }
+ _moveField forward
+
+ #
+ # A ctrl-tab key moves the hour:minute:second field backwards by one
+ # unless the current field is the hour. In that case we'll let
+ # tab take the focus to a previous widget.
+ #
+ } elseif {$state == 4} {
+ if {$_cfield == "hour"} {
+ _setField hour
+ return -code continue
+ }
+ _moveField backward
+ }
+ }
+
+ Right {
+ #
+ # A right arrow key moves the insert cursor to the right one.
+ #
+ $_forward
+ }
+
+ Left - BackSpace - Delete {
+ #
+ # A left arrow, backspace, or delete key moves the insert cursor
+ # to the left one. This is what you expect for the left arrow
+ # and since the whole widget always operates in overstrike mode,
+ # it makes the most sense for backspace and delete to do the same.
+ #
+ $_backward
+ }
+
+ Return {
+ #
+ # A Return key invokes the optionally specified command option.
+ #
+ uplevel #0 $itk_option(-command)
+ }
+
+ default {
+
+ }
+ }
+
+ return -code break
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _toggleAmPm
+#
+# Internal method which toggles the displayed time
+# between "AM" and "PM" when format is "civilian".
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_toggleAmPm {} {
+ set firstChar [string index $_timeVar 9]
+ $itk_component(time) delete 9 10
+ $itk_component(time) insert 9 [expr {($firstChar == "A") ? "P" : "A"}]
+ $itk_component(time) icursor 9
+ set _timeVar [$itk_component(time) get]
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _setField field
+#
+# Adjusts the current field to be that of the argument, setting the
+# insert cursor appropriately.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_setField {field} {
+
+ # Move the position of the cursor to the first character of the
+ # field given by the argument:
+ #
+ # Field First Character Index
+ # ----- ---------------------
+ # hour 0
+ # minute 3
+ # second 6
+ # ampm 9
+ #
+ switch $field {
+ hour {
+ $itk_component(time) icursor 0
+ }
+ minute {
+ $itk_component(time) icursor 3
+ }
+ second {
+ $itk_component(time) icursor 6
+ }
+ ampm {
+ if {$itk_option(-format) == "military"} {
+ error "bad field: \"$field\", must be hour, minute or second"
+ }
+ $itk_component(time) icursor 9
+ }
+ default {
+ if {$itk_option(-format) == "military"} {
+ error "bad field: \"$field\", must be hour, minute or second"
+ } else {
+ error "bad field: \"$field\", must be hour, minute, second or ampm"
+ }
+ }
+ }
+
+ set _cfield $field
+
+ return $_cfield
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _moveField
+#
+# Moves the cursor one field forward or backward.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_moveField {direction} {
+
+ # Since the value "_fields" list variable is always either value:
+ # military => {hour minute second}
+ # civilian => {hour minute second ampm}
+ #
+ # the index of the previous or next field index can be determined
+ # by subtracting or adding 1 to current the index, respectively.
+ #
+ set index [lsearch $_fields $_cfield]
+ expr {($direction == "forward") ? [incr index] : [incr index -1]}
+
+ if {$index == $_numFields} {
+ set index 0
+ } elseif {$index < 0} {
+ set index [expr {$_numFields-1}]
+ }
+
+ _setField [lindex $_fields $index]
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _whichField
+#
+# Returns the current field that the cursor is positioned within.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_whichField {} {
+
+ # Return the current field based on the position of the cursor.
+ #
+ # Field Index
+ # ----- -----
+ # hour 0,1
+ # minute 3,4
+ # second 6,7
+ # ampm 9,10
+ #
+ set icursor [$itk_component(time) index insert]
+ switch $icursor {
+ 0 - 1 {
+ set _cfield hour
+ }
+ 3 - 4 {
+ set _cfield minute
+ }
+ 6 - 7 {
+ set _cfield second
+ }
+ 9 - 10 {
+ set _cfield ampm
+ }
+ }
+
+ return $_cfield
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _forwardCivilian
+#
+# Internal method which moves the cursor forward by one character
+# jumping over the slashes and wrapping.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_forwardCivilian {} {
+
+ #
+ # If the insertion cursor is at the second digit
+ # of either the hour, minute or second field, then
+ # move the cursor to the first digit of the right-most field.
+ #
+ # else move the insertion cursor right one character
+ #
+ set icursor [$itk_component(time) index insert]
+ switch $icursor {
+ 1 {
+ _setField minute
+ }
+ 4 {
+ _setField second
+ }
+ 7 {
+ _setField ampm
+ }
+ 9 - 10 {
+ _setField hour
+ }
+ default {
+ $itk_component(time) icursor [expr {$icursor+1}]
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _forwardMilitary
+#
+# Internal method which moves the cursor forward by one character
+# jumping over the slashes and wrapping.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_forwardMilitary {} {
+
+ #
+ # If the insertion cursor is at the second digit of either
+ # the hour, minute or second field, then move the cursor to
+ # the first digit of the right-most field.
+ #
+ # else move the insertion cursor right one character
+ #
+ set icursor [$itk_component(time) index insert]
+ switch $icursor {
+ 1 {
+ _setField minute
+ }
+ 4 {
+ _setField second
+ }
+ 7 {
+ _setField hour
+ }
+ default {
+ $itk_component(time) icursor [expr {$icursor+1}]
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _backwardCivilian
+#
+# Internal method which moves the cursor backward by one character
+# jumping over the ":" and wrapping.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_backwardCivilian {} {
+
+ #
+ # If the insertion cursor is at the first character
+ # of either the minute or second field or at the ampm
+ # field, then move the cursor to the second character
+ # of the left-most field.
+ #
+ # else if the insertion cursor is at the first digit of the
+ # hour field, then move the cursor to the first character
+ # of the ampm field.
+ #
+ # else move the insertion cursor left one character
+ #
+ set icursor [$itk_component(time) index insert]
+ switch $icursor {
+ 9 {
+ _setField second
+ $itk_component(time) icursor 7
+ }
+ 6 {
+ _setField minute
+ $itk_component(time) icursor 4
+ }
+ 3 {
+ _setField hour
+ $itk_component(time) icursor 1
+ }
+ 0 {
+ _setField ampm
+ $itk_component(time) icursor 9
+ }
+ default {
+ $itk_component(time) icursor [expr {$icursor-1}]
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# PROTECTED METHOD: _backwardMilitary
+#
+# Internal method which moves the cursor backward by one character
+# jumping over the slashes and wrapping.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Timefield::_backwardMilitary {} {
+
+ #
+ # If the insertion cursor is at the first digit of either
+ # the minute or second field, then move the cursor to the
+ # second character of the left-most field.
+ #
+ # else if the insertion cursor is at the first digit of the
+ # hour field, then move the cursor to the second digit
+ # of the second field.
+ #
+ # else move the insertion cursor left one character
+ #
+ set icursor [$itk_component(time) index insert]
+ switch $icursor {
+ 6 {
+ _setField minute
+ $itk_component(time) icursor 4
+ }
+ 3 {
+ _setField hour
+ $itk_component(time) icursor 1
+ }
+ 0 {
+ _setField second
+ $itk_component(time) icursor 7
+ }
+ default {
+ $itk_component(time) icursor [expr {$icursor-1}]
+ }
+ }
+}
diff --git a/iwidgets/generic/toolbar.itk b/iwidgets/generic/toolbar.itk
new file mode 100644
index 00000000000..f49d7aa8348
--- /dev/null
+++ b/iwidgets/generic/toolbar.itk
@@ -0,0 +1,983 @@
+#
+# Toolbar
+# ----------------------------------------------------------------------
+#
+# The Toolbar command creates a new window (given by the pathName
+# argument) and makes it into a Tool Bar widget. Additional options,
+# described above may be specified on the command line or in the
+# option database to configure aspects of the Toolbar such as its
+# colors, font, and orientation. The Toolbar command returns its
+# pathName argument. At the time this command is invoked, there
+# must not exist a window named pathName, but pathName's parent
+# must exist.
+#
+# A Toolbar is a widget that displays a collection of widgets arranged
+# either in a row or a column (depending on the value of the -orient
+# option). This collection of widgets is usually for user convenience
+# to give access to a set of commands or settings. Any widget may be
+# placed on a Toolbar. However, command or value-oriented widgets (such
+# as button, radiobutton, etc.) are usually the most useful kind of
+# widgets to appear on a Toolbar.
+#
+# WISH LIST:
+# This section lists possible future enhancements.
+#
+# Toggle between text and image/bitmap so that the toolbar could
+# display either all text or all image/bitmaps.
+# Implementation of the -toolbarfile option that allows toolbar
+# add commands to be read in from a file.
+# ----------------------------------------------------------------------
+# AUTHOR: Bill W. Scott EMAIL: bscott@spd.dsccc.com
+#
+# @(#) $Id$
+# ----------------------------------------------------------------------
+# 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.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Toolbar*padX 5 widgetDefault
+option add *Toolbar*padY 5 widgetDefault
+option add *Toolbar*orient horizontal widgetDefault
+option add *Toolbar*highlightThickness 0 widgetDefault
+option add *Toolbar*indicatorOn false widgetDefault
+option add *Toolbar*selectColor [. cget -bg] widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Toolbar {
+ keep -activebackground -activeforeground -background -balloonbackground \
+ -balloondelay1 -balloondelay2 -balloonfont -balloonforeground \
+ -borderwidth -cursor -disabledforeground -font -foreground \
+ -highlightbackground -highlightcolor -highlightthickness \
+ -insertbackground -insertforeground -selectbackground \
+ -selectborderwidth -selectcolor -selectforeground -troughcolor
+}
+
+# ------------------------------------------------------------------
+# TOOLBAR
+# ------------------------------------------------------------------
+itcl::class iwidgets::Toolbar {
+ inherit itk::Widget
+
+ constructor {args} {}
+ destructor {}
+
+ itk_option define -balloonbackground \
+ balloonBackground BalloonBackground yellow
+ itk_option define -balloonforeground \
+ balloonForeground BalloonForeground black
+ itk_option define -balloonfont balloonFont BalloonFont 6x10
+ itk_option define -balloondelay1 \
+ balloonDelay1 BalloonDelay1 1000
+ itk_option define -balloondelay2 \
+ balloonDelay2 BalloonDelay2 200
+ itk_option define -helpvariable helpVariable HelpVariable {}
+ itk_option define -orient orient Orient "horizontal"
+
+ #
+ # The following options implement propogated configurations to
+ # any widget that might be added to us. The problem is this is
+ # not deterministic as someone might add a new kind of widget with
+ # and option like -armbackground, so we would not be aware of
+ # this kind of option. Anyway we support as many of the obvious
+ # ones that we can. They can always configure them with itemconfigures.
+ #
+ itk_option define -activebackground activeBackground Foreground #c3c3c3
+ itk_option define -activeforeground activeForeground Background Black
+ itk_option define -background background Background #d9d9d9
+ itk_option define -borderwidth borderWidth BorderWidth 2
+ itk_option define -cursor cursor Cursor {}
+ itk_option define -disabledforeground \
+ disabledForeground DisabledForeground #a3a3a3
+ itk_option define -font \
+ font Font "-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*"
+ itk_option define -foreground foreground Foreground #000000000000
+ itk_option define -highlightbackground \
+ highlightBackground HighlightBackground #d9d9d9
+ itk_option define -highlightcolor highlightColor HighlightColor Black
+ itk_option define -highlightthickness \
+ highlightThickness HighlightThickness 0
+ itk_option define -insertforeground insertForeground Background #c3c3c3
+ itk_option define -insertbackground insertBackground Foreground Black
+ itk_option define -selectbackground selectBackground Foreground #c3c3c3
+ itk_option define -selectborderwidth selectBorderWidth BorderWidth {}
+ itk_option define -selectcolor selectColor Background #b03060
+ itk_option define -selectforeground selectForeground Background Black
+ itk_option define -state state State normal
+ itk_option define -troughcolor troughColor Background #c3c3c3
+
+ public method add {widgetCommand name args}
+ public method delete {args}
+ public method index {index}
+ public method insert {beforeIndex widgetCommand name args}
+ public method itemcget {index args}
+ public method itemconfigure {index args}
+
+ public method _resetBalloonTimer {}
+ public method _startBalloonDelay {window}
+ public method _stopBalloonDelay {window balloonClick}
+
+ private method _deleteWidgets {index1 index2}
+ private method _addWidget {widgetCommand name args}
+ private method _index {toolList index}
+ private method _getAttachedOption {optionListName widget args retValue}
+ private method _setAttachedOption {optionListName widget option args}
+ private method _packToolbar {}
+
+ public method hideHelp {}
+ public method showHelp {window}
+ public method showBalloon {window}
+ public method hideBalloon {}
+
+ private variable _balloonTimer 0
+ private variable _balloonAfterID 0
+ private variable _balloonClick false
+
+ private variable _interior {}
+ private variable _initialMapping 1 ;# Is this the first mapping?
+ private variable _toolList {} ;# List of all widgets on toolbar
+ private variable _opts ;# New options for child widgets
+ private variable _currHelpWidget {} ;# Widget currently displaying help for
+ private variable _hintWindow {} ;# Balloon help bubble.
+
+ # list of options we want to propogate to widgets added to toolbar.
+ private common _optionList {
+ -activebackground \
+ -activeforeground \
+ -background \
+ -borderwidth \
+ -cursor \
+ -disabledforeground \
+ -font \
+ -foreground \
+ -highlightbackground \
+ -highlightcolor \
+ -highlightthickness \
+ -insertbackground \
+ -insertforeground \
+ -selectbackground \
+ -selectborderwidth \
+ -selectcolor \
+ -selectforeground \
+ -state \
+ -troughcolor \
+ }
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Toolbar::constructor {args} {
+ component hull configure -borderwidth 0
+ set _interior $itk_interior
+
+ #
+ # Handle configs
+ #
+ eval itk_initialize $args
+
+ # build balloon help window
+ set _hintWindow [toplevel $itk_component(hull).balloonHintWindow]
+ wm withdraw $_hintWindow
+ label $_hintWindow.label \
+ -foreground $itk_option(-balloonforeground) \
+ -background $itk_option(-balloonbackground) \
+ -font $itk_option(-balloonfont) \
+ -relief raised \
+ -borderwidth 1
+ pack $_hintWindow.label
+
+ # ... Attach help handler to this widget
+ bind toolbar-help-$itk_component(hull) \
+ <Enter> "+[itcl::code $this showHelp %W]"
+ bind toolbar-help-$itk_component(hull) \
+ <Leave> "+[itcl::code $this hideHelp]"
+
+ # ... Set up Microsoft style balloon help display.
+ set _balloonTimer $itk_option(-balloondelay1)
+ bind $_interior \
+ <Leave> "+[itcl::code $this _resetBalloonTimer]"
+ bind toolbar-balloon-$itk_component(hull) \
+ <Enter> "+[itcl::code $this _startBalloonDelay %W]"
+ bind toolbar-balloon-$itk_component(hull) \
+ <Leave> "+[itcl::code $this _stopBalloonDelay %W false]"
+ bind toolbar-balloon-$itk_component(hull) \
+ <Button-1> "+[itcl::code $this _stopBalloonDelay %W true]"
+}
+
+#
+# Provide a lowercase access method for the Toolbar class
+#
+proc ::iwidgets::toolbar {pathName args} {
+ uplevel ::iwidgets::Toolbar $pathName $args
+}
+
+# ------------------------------------------------------------------
+# DESTURCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Toolbar::destructor {} {
+ if {$_balloonAfterID != 0} {after cancel $_balloonAfterID}
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION -balloonbackground
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Toolbar::balloonbackground {
+ if { $_hintWindow != {} } {
+ if { $itk_option(-balloonbackground) != {} } {
+ $_hintWindow.label configure \
+ -background $itk_option(-balloonbackground)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION -balloonforeground
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Toolbar::balloonforeground {
+ if { $_hintWindow != {} } {
+ if { $itk_option(-balloonforeground) != {} } {
+ $_hintWindow.label configure \
+ -foreground $itk_option(-balloonforeground)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION -balloonfont
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Toolbar::balloonfont {
+ if { $_hintWindow != {} } {
+ if { $itk_option(-balloonfont) != {} } {
+ $_hintWindow.label configure \
+ -font $itk_option(-balloonfont)
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: -orient
+#
+# Position buttons either horizontally or vertically.
+# ------------------------------------------------------------------
+itcl::configbody iwidgets::Toolbar::orient {
+ switch $itk_option(-orient) {
+ "horizontal" - "vertical" {
+ _packToolbar
+ }
+ default {error "Invalid orientation. Must be either \
+ horizontal or vertical"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# METHODS
+# ------------------------------------------------------------------
+
+# -------------------------------------------------------------
+# METHOD: add widgetCommand name ?option value?
+#
+# Adds a widget with the command widgetCommand whose name is
+# name to the Toolbar. If widgetCommand is radiobutton
+# or checkbutton, its packing is slightly padded to match the
+# geometry of button widgets.
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::add { widgetCommand name args } {
+
+ eval "_addWidget $widgetCommand $name $args"
+
+ lappend _toolList $itk_component($name)
+
+ if { $widgetCommand == "radiobutton" || \
+ $widgetCommand == "checkbutton" } {
+ set iPad 1
+ } else {
+ set iPad 0
+ }
+
+ # repack the tool bar
+ _packToolbar
+
+ return $itk_component($name)
+
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: delete index ?index2?
+#
+# This command deletes all components between index and
+# index2 inclusive. If index2 is omitted then it defaults
+# to index. Returns an empty string
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::delete { args } {
+ # empty toolbar
+ if { $_toolList == {} } {
+ error "can't delete widget, no widgets in the Toolbar \
+ \"$itk_component(hull)\""
+ }
+
+ set len [llength $args]
+ switch -- $len {
+ 1 {
+ set fromWidget [_index $_toolList [lindex $args 0]]
+
+ if { $fromWidget < 0 || $fromWidget >= [llength $_toolList] } {
+ error "bad Toolbar widget index in delete method: \
+ should be between 0 and [expr {[llength $_toolList] - 1} ]"
+ }
+
+ set toWidget $fromWidget
+ _deleteWidgets $fromWidget $toWidget
+ }
+
+ 2 {
+ set fromWidget [_index $_toolList [lindex $args 0]]
+
+ if { $fromWidget < 0 || $fromWidget >= [llength $_toolList] } {
+ error "bad Toolbar widget index1 in delete method: \
+ should be between 0 and [expr {[llength $_toolList] - 1} ]"
+ }
+
+ set toWidget [_index $_toolList [lindex $args 1]]
+
+ if { $toWidget < 0 || $toWidget >= [llength $_toolList] } {
+ error "bad Toolbar widget index2 in delete method: \
+ should be between 0 and [expr {[llength $_toolList] - 1} ]"
+ }
+
+ if { $fromWidget > $toWidget } {
+ error "bad Toolbar widget index1 in delete method: \
+ index1 is greater than index2"
+ }
+
+ _deleteWidgets $fromWidget $toWidget
+ }
+
+ default {
+ # ... too few/many parameters passed
+ error "wrong # args: should be \
+ \"$itk_component(hull) delete index1 ?index2?\""
+ }
+ }
+
+ return {}
+}
+
+
+# -------------------------------------------------------------
+#
+# METHOD: index index
+#
+# Returns the widget's numerical index for the entry corresponding
+# to index. If index is not found, -1 is returned
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::index { index } {
+
+ return [_index $_toolList $index]
+
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: insert beforeIndex widgetCommand name ?option value?
+#
+# Insert a new component named name with the command
+# widgetCommand before the com ponent specified by beforeIndex.
+# If widgetCommand is radiobutton or checkbutton, its packing
+# is slightly padded to match the geometry of button widgets.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::insert { beforeIndex widgetCommand name args } {
+
+ set beforeIndex [_index $_toolList $beforeIndex]
+
+ if {$beforeIndex < 0 || $beforeIndex > [llength $_toolList] } {
+ error "bad toolbar entry index $beforeIndex"
+ }
+
+ eval "_addWidget $widgetCommand $name $args"
+
+ # linsert into list
+ set _toolList [linsert $_toolList $beforeIndex $itk_component($name)]
+
+ # repack the tool bar
+ _packToolbar
+
+ return $itk_component($name)
+
+}
+
+# ----------------------------------------------------------------------
+# METHOD: itemcget index ?option?
+#
+# Returns the value for the option setting of the widget at index $index.
+# index can be numeric or widget name
+#
+# ----------------------------------------------------------------------
+itcl::body iwidgets::Toolbar::itemcget { index args} {
+
+ return [lindex [eval itemconfigure $index $args] 4]
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: itemconfigure index ?option? ?value? ?option value...?
+#
+# Query or modify the configuration options of the widget of
+# the Toolbar specified by index. If no option is specified,
+# returns a list describing all of the available options for
+# index (see Tk_ConfigureInfo for information on the format
+# of this list). If option is specified with no value, then
+# the command returns a list describing the one named option
+# (this list will be identical to the corresponding sublist
+# of the value returned if no option is specified). If one
+# or more option-value pairs are specified, then the command
+# modifies the given widget option(s) to have the given
+# value(s); in this case the command returns an empty string.
+# The component type of index determines the valid available options.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::itemconfigure { index args } {
+
+ # Get a numeric index.
+ set index [_index $_toolList $index]
+
+ # Get the tool path
+ set toolPath [lindex $_toolList $index]
+
+ set len [llength $args]
+
+ switch $len {
+ 0 {
+ # show all options
+ # ''''''''''''''''
+
+ # support display of -helpstr and -balloonstr configs
+ set optList [$toolPath configure]
+
+ ## @@@ might want to use _getAttachedOption instead...
+ if { [info exists _opts($toolPath,-helpstr)] } {
+ set value $_opts($toolPath,-helpstr)
+ } else {
+ set value {}
+ }
+ lappend optList [list -helpstr helpStr HelpStr {} $value]
+ if { [info exists _opts($toolPath,-balloonstr)] } {
+ set value $_opts($toolPath,-balloonstr)
+ } else {
+ set value {}
+ }
+ lappend optList [list -balloonstr balloonStr BalloonStr {} $value]
+ return $optList
+ }
+ 1 {
+ # show only option specified
+ # ''''''''''''''''''''''''''
+ # did we satisfy the option get request?
+
+ if { [regexp -- {-helpstr} $args] } {
+ if { [info exists _opts($toolPath,-helpstr)] } {
+ set value $_opts($toolPath,-helpstr)
+ } else {
+ set value {}
+ }
+ return [list -helpstr helpStr HelpStr {} $value]
+ } elseif { [regexp -- {-balloonstr} $args] } {
+ if { [info exists _opts($toolPath,-balloonstr)] } {
+ set value $_opts($toolPath,-balloonstr)
+ } else {
+ set value {}
+ }
+ return [list -balloonstr balloonStr BalloonStr {} $value]
+ } else {
+ return [eval $toolPath configure $args]
+ }
+
+ }
+ default {
+ # ... do a normal configure
+
+ # first screen for all our child options we are adding
+ _setAttachedOption \
+ _opts \
+ $toolPath \
+ "-helpstr" \
+ $args
+
+ _setAttachedOption \
+ _opts \
+ $toolPath \
+ "-balloonstr" \
+ $args
+
+ # with a clean args list do a configure
+
+ # if the stripping process brought us down to no options
+ # to set, then forget the configure of widget.
+ if { [llength $args] != 0 } {
+ return [eval $toolPath configure $args]
+ } else {
+ return ""
+ }
+ }
+ }
+
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: _resetBalloonDelay1
+#
+# Sets the delay that will occur before a balloon could be popped
+# up to balloonDelay1
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::_resetBalloonTimer {} {
+ set _balloonTimer $itk_option(-balloondelay1)
+
+ # reset the <1> longer delay
+ set _balloonClick false
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: _startBalloonDelay
+#
+# Starts waiting to pop up a balloon id
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::_startBalloonDelay {window} {
+ if {$_balloonAfterID != 0} {
+ after cancel $_balloonAfterID
+ }
+ set _balloonAfterID [after $_balloonTimer [itcl::code $this showBalloon $window]]
+}
+
+# -------------------------------------------------------------
+#
+# METHOD: _stopBalloonDelay
+#
+# This method will stop the timer for a balloon popup if one is
+# in progress. If however there is already a balloon window up
+# it will hide the balloon window and set timing to delay 2 stage.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::_stopBalloonDelay { window balloonClick } {
+
+ # If <1> then got a click cancel
+ if { $balloonClick } {
+ set _balloonClick true
+ }
+ if { $_balloonAfterID != 0 } {
+ after cancel $_balloonAfterID
+ set _balloonAfterID 0
+ } else {
+ hideBalloon
+
+ # If this was cancelled with a <1> use longer delay.
+ if { $_balloonClick } {
+ set _balloonTimer $itk_option(-balloondelay1)
+ } else {
+ set _balloonTimer $itk_option(-balloondelay2)
+ }
+ }
+}
+
+# -------------------------------------------------------------
+# PRIVATE METHOD: _addWidget
+#
+# widgetCommand : command to invoke to create the added widget
+# name : name of the new widget to add
+# args : options for the widget create command
+#
+# Looks for -helpstr, -balloonstr and grabs them, strips from
+# args list. Then tries to add a component and keeps based
+# on known type. If it fails, it tries to clean up. Then it
+# binds handlers for helpstatus and balloon help.
+#
+# Returns the path of the widget added.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::_addWidget { widgetCommand name args } {
+
+ # ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ # Add the widget to the tool bar
+ # '''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+ # ... Strip out and save the -helpstr, -balloonstr options from args
+ # and save it in _opts
+ _setAttachedOption \
+ _opts \
+ $_interior.$name \
+ -helpstr \
+ $args
+
+ _setAttachedOption \
+ _opts \
+ $_interior.$name \
+ -balloonstr \
+ $args
+
+
+ # ... Add the new widget as a component (catch an error if occurs)
+ set createFailed [catch {
+ itk_component add $name {
+ eval $widgetCommand $_interior.$name $args
+ } {
+ }
+ } errMsg]
+
+ # ... Clean up if the create failed, and exit.
+ # The _opts list if it has -helpstr, -balloonstr just entered for
+ # this, it must be cleaned up.
+ if { $createFailed } {
+ # clean up
+ if {![catch {set _opts($_interior.$name,-helpstr)}]} {
+ set lastIndex [\
+ expr {[llength \
+ $_opts($_interior.$name,-helpstr) ]-1}]
+ lreplace $_opts($_interior.$name,-helpstr) \
+ $lastIndex $lastIndex ""
+ }
+ if {![catch {set _opts($_interior.$name,-balloonstr)}]} {
+ set lastIndex [\
+ expr {[llength \
+ $_opts($_interior.$name,-balloonstr) ]-1}]
+ lreplace $_opts($_interior.$name,-balloonstr) \
+ $lastIndex $lastIndex ""
+ }
+ error $errMsg
+ }
+
+ # ... Add in dynamic options that apply from the _optionList
+ foreach optionSet [$itk_component($name) configure] {
+ set option [lindex $optionSet 0]
+ if { [lsearch $_optionList $option] != -1 } {
+ itk_option add $name.$option
+ }
+ }
+
+ bindtags $itk_component($name) \
+ [linsert [bindtags $itk_component($name)] end \
+ toolbar-help-$itk_component(hull)]
+ bindtags $itk_component($name) \
+ [linsert [bindtags $itk_component($name)] end \
+ toolbar-balloon-$itk_component(hull)]
+
+ return $itk_component($name)
+}
+
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _deleteWidgets
+#
+# deletes widget range by numerical index numbers.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::_deleteWidgets { index1 index2 } {
+
+ for { set index $index1 } { $index <= $index2 } { incr index } {
+
+ # kill the widget
+ set component [lindex $_toolList $index]
+ destroy $component
+
+ }
+
+ # physically remove the page
+ set _toolList [lreplace $_toolList $index1 $index2]
+
+}
+
+# -------------------------------------------------------------
+# PRIVATE METHOD: _index
+#
+# toolList : list of widget names to search thru if index
+# is non-numeric
+# index : either number, 'end', 'last', or pattern
+#
+# _index takes takes the value $index converts it to
+# a numeric identifier. If the value is not already
+# an integer it looks it up in the $toolList array.
+# If it fails it returns -1
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::_index { toolList index } {
+
+ switch -- $index {
+ end - last {
+ set number [expr {[llength $toolList] -1}]
+ }
+ default {
+ # is it a number already? Then just use the number
+ if { [regexp {^[0-9]+$} $index] } {
+ set number $index
+ # check bounds
+ if { $number < 0 || $number >= [llength $toolList] } {
+ set number -1
+ }
+ # otherwise it is a widget name
+ } else {
+ if { [catch { set itk_component($index) } ] } {
+ set number -1
+ } else {
+ set number [lsearch -exact $toolList \
+ $itk_component($index)]
+ }
+ }
+ }
+ }
+
+ return $number
+}
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# STATUS HELP for linking to helpVariable
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# -------------------------------------------------------------
+#
+# PUBLIC METHOD: hideHelp
+#
+# Bound to the <Leave> event on a toolbar widget. This clears the
+# status widget help area and resets the help entry.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::hideHelp {} {
+ if { $itk_option(-helpvariable) != {} } {
+ upvar #0 $itk_option(-helpvariable) helpvar
+ set helpvar {}
+ }
+ set _currHelpWidget {}
+}
+
+# -------------------------------------------------------------
+#
+# PUBLIC METHOD: showHelp
+#
+# Bound to the <Motion> event on a tool bar widget. This puts the
+# help string associated with the tool bar widget into the
+# status widget help area. If no help exists for the current
+# entry, the status widget is cleared.
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::showHelp { window } {
+
+ set widgetPath $window
+ # already on this item?
+ if { $window == $_currHelpWidget } {
+ return
+ }
+
+ set _currHelpWidget $window
+
+ # Do we have a helpvariable set on the toolbar?
+ if { $itk_option(-helpvariable) != {} } {
+ upvar #0 $itk_option(-helpvariable) helpvar
+
+ # is the -helpstr set for this widget?
+ set args "-helpstr"
+ if {[_getAttachedOption _opts \
+ $window args value]} {
+ set helpvar $value.
+ } else {
+ set helpvar {}
+ }
+ }
+}
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# BALLOON HELP for show/hide of hint window
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# -------------------------------------------------------------
+#
+# PUBLIC METHOD: showBalloon
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::showBalloon {window} {
+ set _balloonClick false
+ set _balloonAfterID 0
+ # Are we still inside the window?
+ set mouseWindow \
+ [winfo containing [winfo pointerx .] [winfo pointery .]]
+
+ if { [string match $window* $mouseWindow] } {
+ # set up the balloonString
+ set args "-balloonstr"
+ if {[_getAttachedOption _opts \
+ $window args hintStr]} {
+ # configure the balloon help
+ $_hintWindow.label configure -text $hintStr
+
+ # Coordinates of the balloon
+ set balloonLeft \
+ [expr {[winfo rootx $window] + round(([winfo width $window]/2.0))}]
+ set balloonTop \
+ [expr {[winfo rooty $window] + [winfo height $window]}]
+
+ # put up balloon window
+ wm overrideredirect $_hintWindow 0
+ wm geometry $_hintWindow "+$balloonLeft+$balloonTop"
+ wm overrideredirect $_hintWindow 1
+ wm deiconify $_hintWindow
+ raise $_hintWindow
+ } else {
+ #NO BALLOON HELP AVAILABLE
+ }
+ } else {
+ #NOT IN BUTTON
+ }
+
+}
+
+# -------------------------------------------------------------
+#
+# PUBLIC METHOD: hideBalloon
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::hideBalloon {} {
+ wm withdraw $_hintWindow
+}
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# OPTION MANAGEMENT for -helpstr, -balloonstr
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# -------------------------------------------------------------
+# PRIVATE METHOD: _getAttachedOption
+#
+# optionListName : the name of the array that holds all attached
+# options. It is indexed via widget,option to get
+# the value.
+# widget : the widget that the option is associated with
+# option : the option whose value we are looking for on
+# this widget.
+#
+# expects to be called only if the $option is length 1
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::_getAttachedOption { optionListName widget args retValue} {
+
+ # get a reference to the option, so we can change it.
+ upvar $args argsRef
+ upvar $retValue retValueRef
+
+ set success false
+
+ if { ![catch { set retValueRef \
+ [eval set [subst [set optionListName]]($widget,$argsRef)]}]} {
+
+ # remove the option argument
+ set success true
+ set argsRef ""
+ }
+
+ return $success
+}
+
+# -------------------------------------------------------------
+# PRIVATE METHOD: _setAttachedOption
+#
+# This method allows us to attach new options to a widget. It
+# catches the 'option' to be attached, strips it out of 'args'
+# attaches it to the 'widget' by stuffing the value into
+# 'optionList(widget,option)'
+#
+# optionListName: where to store the option and widget association
+# widget: is the widget we want to associate the attached option
+# option: is the attached option (unknown to this widget)
+# args: the arg list to search and remove the option from (if found)
+#
+# Modifies the args parameter.
+# Returns boolean indicating the success of the method
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::_setAttachedOption {optionListName widget option args} {
+
+ upvar args argsRef
+
+ set success false
+
+ # check for 'option' in the 'args' list for the 'widget'
+ set optPos [eval lsearch $args $option]
+
+ # ... found it
+ if { $optPos != -1 } {
+ # grab a copy of the option from arg list
+ set [subst [set optionListName]]($widget,$option) \
+ [eval lindex $args [expr {$optPos + 1}]]
+
+ # remove the option argument and value from the arg list
+ set argsRef [eval lreplace $args $optPos [expr {$optPos + 1}]]
+ set success true
+ }
+ # ... if not found, will leave args alone
+
+ return $success
+}
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# GEOMETRY MANAGEMENT for tool widgets
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# -------------------------------------------------------------
+#
+# PRIVATE METHOD: _packToolbar
+#
+#
+#
+# -------------------------------------------------------------
+itcl::body iwidgets::Toolbar::_packToolbar {} {
+
+ # forget the previous locations
+ foreach tool $_toolList {
+ pack forget $tool
+ }
+
+ # pack in order of _toolList.
+ foreach tool $_toolList {
+ # adjust for radios and checks to match buttons
+ if { [winfo class $tool] == "Radiobutton" ||
+ [winfo class $tool] == "Checkbutton" } {
+ set iPad 1
+ } else {
+ set iPad 0
+ }
+
+ # pack by horizontal or vertical orientation
+ if {$itk_option(-orient) == "horizontal" } {
+ pack $tool -side left -fill y \
+ -ipadx $iPad -ipady $iPad
+ } else {
+ pack $tool -side top -fill x \
+ -ipadx $iPad -ipady $iPad
+ }
+ }
+}
diff --git a/iwidgets/generic/unknownimage.gif b/iwidgets/generic/unknownimage.gif
new file mode 100644
index 00000000000..d000bf70258
--- /dev/null
+++ b/iwidgets/generic/unknownimage.gif
Binary files differ
diff --git a/iwidgets/generic/watch.itk b/iwidgets/generic/watch.itk
new file mode 100644
index 00000000000..ace2cc94655
--- /dev/null
+++ b/iwidgets/generic/watch.itk
@@ -0,0 +1,626 @@
+#
+# Watch
+# ----------------------------------------------------------------------
+# Implements a a clock widget in a canvas.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: John A. Tucker EMAIL: jatucker@spd.dsccc.com
+#
+# ======================================================================
+# Copyright (c) 1997 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.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Watch.labelFont \
+ -*-Courier-Medium-R-Normal--*-120-*-*-*-*-*-* widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Watch {
+ keep -background -cursor -labelfont -foreground
+}
+
+itcl::class iwidgets::Watch {
+
+ inherit itk::Widget
+
+ itk_option define -hourradius hourRadius Radius .50
+ itk_option define -hourcolor hourColor Color red
+
+ itk_option define -minuteradius minuteRadius Radius .80
+ itk_option define -minutecolor minuteColor Color yellow
+
+ itk_option define -pivotradius pivotRadius Radius .10
+ itk_option define -pivotcolor pivotColor Color white
+
+ itk_option define -secondradius secondRadius Radius .90
+ itk_option define -secondcolor secondColor Color black
+
+ itk_option define -clockcolor clockColor Color white
+ itk_option define -clockstipple clockStipple ClockStipple {}
+
+ itk_option define -state state State normal
+ itk_option define -showampm showAmPm ShowAmPm true
+
+ itk_option define -tickcolor tickColor Color black
+
+ constructor {args} {}
+ destructor {}
+
+ #
+ # Public methods
+ #
+ public {
+ method get {{format "-string"}}
+ method show {{time "now"}}
+ method watch {args}
+ }
+
+ #
+ # Private methods
+ #
+ private {
+ method _handMotionCB {tag x y}
+ method _drawHand {tag}
+ method _handReleaseCB {tag x y}
+ method _displayClock {{when "later"}}
+
+ variable _interior
+ variable _radius
+ variable _theta
+ variable _extent
+ variable _reposition "" ;# non-null => _displayClock pending
+ variable _timeVar
+ variable _x0 1
+ variable _y0 1
+
+ common _ampmVar
+ common PI [expr {2*asin(1.0)}]
+ }
+}
+
+#
+# Provide a lowercased access method for the Watch class.
+#
+proc ::iwidgets::watch {pathName args} {
+ uplevel ::iwidgets::Watch $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Watch.width 155 widgetDefault
+option add *Watch.height 175 widgetDefault
+
+# -----------------------------------------------------------------------------
+# CONSTRUCTOR
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::constructor { args } {
+ #
+ # Add back to the hull width and height options and make the
+ # borderwidth zero since we don't need it.
+ #
+ set _interior $itk_interior
+
+ itk_option add hull.width hull.height
+ component hull configure -borderwidth 0
+ grid propagate $itk_component(hull) no
+
+ set _ampmVar($this) "AM"
+ set _radius(outer) 1
+
+ set _radius(hour) 1
+ set _radius(minute) 1
+ set _radius(second) 1
+
+ set _theta(hour) 30
+ set _theta(minute) 6
+ set _theta(second) 6
+
+ set _extent(hour) 14
+ set _extent(minute) 14
+ set _extent(second) 2
+
+ set _timeVar(hour) 12
+ set _timeVar(minute) 0
+ set _timeVar(second) 0
+
+ #
+ # Create the frame in which the "AM" and "PM" radiobuttons will be drawn
+ #
+ itk_component add frame {
+ frame $itk_interior.frame
+ }
+
+ #
+ # Create the canvas in which the clock will be drawn
+ #
+ itk_component add canvas {
+ canvas $itk_interior.canvas
+ }
+ bind $itk_component(canvas) <Map> +[itcl::code $this _displayClock]
+ bind $itk_component(canvas) <Configure> +[itcl::code $this _displayClock]
+
+ #
+ # Create the "AM" and "PM" radiobuttons to be drawn in the canvas
+ #
+ itk_component add am {
+ radiobutton $itk_component(frame).am \
+ -text "AM" \
+ -value "AM" \
+ -variable [itcl::scope _ampmVar($this)]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ itk_component add pm {
+ radiobutton $itk_component(frame).pm \
+ -text "PM" \
+ -value "PM" \
+ -variable [itcl::scope _ampmVar($this)]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ #
+ # Create the canvas item for displaying the main oval which encapsulates
+ # the entire clock.
+ #
+ watch create oval 0 0 2 2 -width 5 -tags clock
+
+ #
+ # Create the canvas items for displaying the 60 ticks marks around the
+ # inner perimeter of the watch.
+ #
+ set extent 3
+ for {set i 0} {$i < 60} {incr i} {
+ set start [expr {$i*6-1}]
+ set tag [expr {[expr {$i%5}] == 0 ? "big" : "little"}]
+ watch create arc 0 0 0 0 \
+ -style arc \
+ -extent $extent \
+ -start $start \
+ -tags "tick$i tick $tag"
+ }
+
+ #
+ # Create the canvas items for displaying the hour, minute, and second hands
+ # of the watch. Add bindings to allow the mouse to move and set the
+ # clock hands.
+ #
+ watch create arc 1 1 1 1 -extent 30 -tags minute
+ watch create arc 1 1 1 1 -extent 30 -tags hour
+ watch create arc 1 1 1 1 -tags second
+
+ #
+ # Create the canvas item for displaying the center of the watch in which
+ # the hour, minute, and second hands will pivot.
+ #
+ watch create oval 0 0 1 1 -width 5 -fill black -tags pivot
+
+ #
+ # Position the "AM/PM" button frame and watch canvas.
+ #
+ grid $itk_component(frame) -row 0 -column 0 -sticky new
+ grid $itk_component(canvas) -row 1 -column 0 -sticky nsew
+
+ grid rowconfigure $itk_interior 0 -weight 0
+ grid rowconfigure $itk_interior 1 -weight 1
+ grid columnconfigure $itk_interior 0 -weight 1
+
+ eval itk_initialize $args
+}
+
+# -----------------------------------------------------------------------------
+# DESTURCTOR
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::destructor {} {
+ if {$_reposition != ""} {
+ after cancel $_reposition
+ }
+}
+
+# -----------------------------------------------------------------------------
+# METHODS
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# METHOD: _handReleaseCB tag x y
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::_handReleaseCB {tag x y} {
+
+ set atanab [expr {atan2(double($y-$_y0),double($x-$_x0))*(180/$PI)}]
+ set degrees [expr {$atanab > 0 ? [expr {360-$atanab}] : abs($atanab)}]
+ set ticks [expr {round($degrees/$_theta($tag))}]
+ set _timeVar($tag) [expr {((450-$ticks*$_theta($tag))%360)/$_theta($tag)}]
+
+ if {$tag == "hour" && $_timeVar(hour) == 0} {
+ set _timeVar($tag) 12
+ }
+
+ _drawHand $tag
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: _handMotionCB tag x y
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::_handMotionCB {tag x y} {
+ if {$x == $_x0 || $y == $_y0} {
+ return
+ }
+
+ set a [expr {$y-$_y0}]
+ set b [expr {$x-$_x0}]
+ set c [expr {hypot($a,$b)}]
+
+ set atanab [expr {atan2(double($a),double($b))*(180/$PI)}]
+ set degrees [expr {$atanab > 0 ? [expr 360-$atanab] : abs($atanab)}]
+
+ set x2 [expr {$_x0+$_radius($tag)*($b/double($c))}]
+ set y2 [expr {$_y0+$_radius($tag)*($a/double($c))}]
+ watch coords $tag \
+ [expr {$x2-$_radius($tag)}] \
+ [expr {$y2-$_radius($tag)}] \
+ [expr {$x2+$_radius($tag)}] \
+ [expr {$y2+$_radius($tag)}]
+ set start [expr {$degrees-180-($_extent($tag)/2)}]
+ watch itemconfigure $tag -start $start -extent $_extent($tag)
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: get ?format?
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::get {{format "-string"}} {
+ set timestr [format "%02d:%02d:%02d %s" \
+ $_timeVar(hour) $_timeVar(minute) \
+ $_timeVar(second) $_ampmVar($this)]
+
+ switch -- $format {
+ "-string" {
+ return $timestr
+ }
+ "-clicks" {
+ return [clock scan $timestr]
+ }
+ default {
+ error "bad format option \"$format\":\
+ should be -string or -clicks"
+ }
+ }
+}
+
+# -----------------------------------------------------------------------------
+# METHOD: watch ?args?
+#
+# Evaluates the specified args against the canvas component.
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::watch {args} {
+ return [eval $itk_component(canvas) $args]
+}
+
+# -----------------------------------------------------------------------------
+# METHOD: _drawHand tag
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::_drawHand {tag} {
+
+ set degrees [expr {abs(450-($_timeVar($tag)*$_theta($tag)))%360}]
+ set radians [expr {$degrees*($PI/180)}]
+ set x [expr {$_x0+$_radius($tag)*cos($radians)}]
+ set y [expr {$_y0+$_radius($tag)*sin($radians)*(-1)}]
+ watch coords $tag \
+ [expr {$x-$_radius($tag)}] \
+ [expr {$y-$_radius($tag)}] \
+ [expr {$x+$_radius($tag)}] \
+ [expr {$y+$_radius($tag)}]
+ set start [expr {$degrees-180-($_extent($tag)/2)}]
+ watch itemconfigure $tag -start $start
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: show time
+#
+# Changes the currently displayed time to be that of the time
+# argument. The time may be specified either as a string or an
+# integer clock value. Reference the clock command for more
+# information on obtaining times and their formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Watch::show {{time "now"}} {
+ if {$time == "now"} {
+ set seconds [clock seconds]
+ } elseif {![catch {clock format $time}]} {
+ set seconds $time
+ } elseif {[catch {set seconds [clock scan $time]}]} {
+ error "bad time: \"$time\", must be a valid time\
+ string, clock clicks value or the keyword now"
+ }
+
+ set timestring [clock format $seconds -format "%I %M %S %p"]
+ set _timeVar(hour) [expr int(1[lindex $timestring 0] - 100)]
+ set _timeVar(minute) [expr int(1[lindex $timestring 1] - 100)]
+ set _timeVar(second) [expr int(1[lindex $timestring 2] - 100)]
+ set _ampmVar($this) [lindex $timestring 3]
+
+ _drawHand hour
+ _drawHand minute
+ _drawHand second
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: _displayClock ?when?
+#
+# Places the hour, minute, and second dials in the canvas. If "when" is "now",
+# the change is applied immediately. If it is "later" or it is not specified,
+# then the change is applied later, when the application is idle.
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::_displayClock {{when "later"}} {
+
+ if {$when == "later"} {
+ if {$_reposition == ""} {
+ set _reposition [after idle [itcl::code $this _displayClock now]]
+ }
+ return
+ }
+
+ #
+ # Compute the center coordinates for the clock based on the
+ # with and height of the canvas.
+ #
+ set width [winfo width $itk_component(canvas)]
+ set height [winfo height $itk_component(canvas)]
+ set _x0 [expr {$width/2}]
+ set _y0 [expr {$height/2}]
+
+ #
+ # Set the radius of the watch, pivot, hour, minute and second items.
+ #
+ set _radius(outer) [expr {$_x0 < $_y0 ? $_x0 : $_y0}]
+ set _radius(pivot) [expr {$itk_option(-pivotradius)*$_radius(outer)}]
+ set _radius(hour) [expr {$itk_option(-hourradius)*$_radius(outer)}]
+ set _radius(minute) [expr {$itk_option(-minuteradius)*$_radius(outer)}]
+ set _radius(second) [expr {$itk_option(-secondradius)*$_radius(outer)}]
+ set outerWidth [watch itemcget clock -width]
+
+ #
+ # Set the coordinates of the clock item
+ #
+ set x1Outer $outerWidth
+ set y1Outer $outerWidth
+ set x2Outer [expr {$width-$outerWidth}]
+ set y2Outer [expr {$height-$outerWidth}]
+ watch coords clock $x1Outer $y1Outer $x2Outer $y2Outer
+
+ #
+ # Set the coordinates of the tick items
+ #
+ set offset [expr {$outerWidth*2}]
+ set x1Tick [expr {$x1Outer+$offset}]
+ set y1Tick [expr {$y1Outer+$offset}]
+ set x2Tick [expr {$x2Outer-$offset}]
+ set y2Tick [expr {$y2Outer-$offset}]
+ for {set i 0} {$i < 60} {incr i} {
+ watch coords tick$i $x1Tick $y1Tick $x2Tick $y2Tick
+ }
+ set maxTickWidth [expr {$_radius(outer)-$_radius(second)+1}]
+ set minTickWidth [expr {round($maxTickWidth/2)}]
+ watch itemconfigure big -width $maxTickWidth
+ watch itemconfigure little -width [expr {round($maxTickWidth/2)}]
+
+ #
+ # Set the coordinates of the pivot item
+ #
+ set x1Center [expr {$_x0-$_radius(pivot)}]
+ set y1Center [expr {$_y0-$_radius(pivot)}]
+ set x2Center [expr {$_x0+$_radius(pivot)}]
+ set y2Center [expr {$_y0+$_radius(pivot)}]
+ watch coords pivot $x1Center $y1Center $x2Center $y2Center
+
+ #
+ # Set the coordinates of the hour, minute, and second dial items
+ #
+ watch itemconfigure hour -extent $_extent(hour)
+ _drawHand hour
+
+ watch itemconfigure minute -extent $_extent(minute)
+ _drawHand minute
+
+ watch itemconfigure second -extent $_extent(second)
+ _drawHand second
+
+ set _reposition ""
+}
+
+# -----------------------------------------------------------------------------
+# OPTIONS
+# -----------------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: state
+#
+# Configure the editable state of the widget. Valid values are
+# normal and disabled. In a disabled state, the hands of the
+# watch are not selectabled.
+# ------------------------------------------------------------------
+itcl::configbody ::iwidgets::Watch::state {
+ if {$itk_option(-state) == "normal"} {
+ watch bind minute <B1-Motion> \
+ [itcl::code $this _handMotionCB minute %x %y]
+ watch bind minute <ButtonRelease-1> \
+ [itcl::code $this _handReleaseCB minute %x %y]
+
+ watch bind hour <B1-Motion> \
+ [itcl::code $this _handMotionCB hour %x %y]
+ watch bind hour <ButtonRelease-1> \
+ [itcl::code $this _handReleaseCB hour %x %y]
+
+ watch bind second <B1-Motion> \
+ [itcl::code $this _handMotionCB second %x %y]
+ watch bind second <ButtonRelease-1> \
+ [itcl::code $this _handReleaseCB second %x %y]
+
+ $itk_component(am) configure -state normal
+ $itk_component(pm) configure -state normal
+
+ } elseif {$itk_option(-state) == "disabled"} {
+ watch bind minute <B1-Motion> {}
+ watch bind minute <ButtonRelease-1> {}
+
+ watch bind hour <B1-Motion> {}
+ watch bind hour <ButtonRelease-1> {}
+
+ watch bind second <B1-Motion> {}
+ watch bind second <ButtonRelease-1> {}
+
+ $itk_component(am) configure -state disabled \
+ -disabledforeground [$itk_component(am) cget -background]
+ $itk_component(pm) configure -state normal \
+ -disabledforeground [$itk_component(am) cget -background]
+
+ } else {
+ error "bad state option \"$itk_option(-state)\":\
+ should be normal or disabled"
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: showampm
+#
+# Configure the display of the AM/PM radio buttons.
+# ------------------------------------------------------------------
+itcl::configbody ::iwidgets::Watch::showampm {
+ switch -- $itk_option(-showampm) {
+ 0 - no - false - off {
+ pack forget $itk_component(am)
+ pack forget $itk_component(pm)
+ }
+
+ 1 - yes - true - on {
+ pack $itk_component(am) -side left -fill both -expand 1
+ pack $itk_component(pm) -side right -fill both -expand 1
+ }
+
+ default {
+ error "bad showampm option \"$itk_option(-showampm)\":\
+ should be boolean"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: pivotcolor
+#
+# Configure the color of the clock pivot.
+#
+itcl::configbody ::iwidgets::Watch::pivotcolor {
+ watch itemconfigure pivot -fill $itk_option(-pivotcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: clockstipple
+#
+# Configure the stipple pattern for the clock fill color.
+#
+itcl::configbody ::iwidgets::Watch::clockstipple {
+ watch itemconfigure clock -stipple $itk_option(-clockstipple)
+}
+
+# ------------------------------------------------------------------
+# OPTION: clockcolor
+#
+# Configure the color of the clock.
+#
+itcl::configbody ::iwidgets::Watch::clockcolor {
+ watch itemconfigure clock -fill $itk_option(-clockcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: hourcolor
+#
+# Configure the color of the hour hand.
+#
+itcl::configbody ::iwidgets::Watch::hourcolor {
+ watch itemconfigure hour -fill $itk_option(-hourcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: minutecolor
+#
+# Configure the color of the minute hand.
+#
+itcl::configbody ::iwidgets::Watch::minutecolor {
+ watch itemconfigure minute -fill $itk_option(-minutecolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: secondcolor
+#
+# Configure the color of the second hand.
+#
+itcl::configbody ::iwidgets::Watch::secondcolor {
+ watch itemconfigure second -fill $itk_option(-secondcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: tickcolor
+#
+# Configure the color of the ticks.
+#
+itcl::configbody ::iwidgets::Watch::tickcolor {
+ watch itemconfigure tick -outline $itk_option(-tickcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: hourradius
+#
+# Configure the radius of the hour hand.
+#
+itcl::configbody ::iwidgets::Watch::hourradius {
+ _displayClock
+}
+
+# ------------------------------------------------------------------
+# OPTION: minuteradius
+#
+# Configure the radius of the minute hand.
+#
+itcl::configbody ::iwidgets::Watch::minuteradius {
+ _displayClock
+}
+
+# ------------------------------------------------------------------
+# OPTION: secondradius
+#
+# Configure the radius of the second hand.
+#
+itcl::configbody ::iwidgets::Watch::secondradius {
+ _displayClock
+}
+