Introduction
Mega-Widgets
Example
Benifits
Look-and-Feel
Extensibility
Flexibility
Lessons Learned
Prospective
Conclusion
Acknowledgments
References
Appendix
What was really needed was the ability to combine Tk widgets together into abstract building blocks called "Mega-Widgets" at the VHLL layer. The [incr Tcl] [1] and [incr Tk] [2] extensions provide this capability, allowing mega-widget development in an object-oriented paradigm using Tcl/Tk rather than C. The next step was to build a mega-widget set in these extensions which replaces the redundant widget combination patterns and provides a foundation for future development. [incr Widgets] is one such extension.
[incr Widgets] is an object-oriented, extensible set of mega-widgets, delivering many general purpose widgets such as option menus, selection boxes, and dialogs whose counterparts are found in Motif. Since [incr Widgets] is based on [incr Tk], the Tk framework of configuration options and widget commands is maintained. In other words, they look, act, and feel like Tk widgets. [incr Widgets] blends with the standard Tk widgets, raising the level of programming and making it easier to consistently develop well styled applications.
The idea of extending the basic Tk widget set is not original. Other mega-widget extensions exist such as Tix [3] and itcl-widgets [4]. Visually, [incr Widgets] covers some of the same ground, successfully replacing many of the same typical combinations. [incr Widgets] differs in the degree of its reusability, extensibility, flexibility, and adherence to the Motif style guide.
The [incr Widgets] mega-widget set is also distinguished by its consistent use of style, built-in intelligence, high degree of flexibility, ease of extending base level functionality, and its object-oriented implementation. Its use has resulted in increased productivity, reliability, and style guide adherence. This paper concentrates on these unique aspects of the widget set and the presentation of its innovative concepts. A pictorial tour with sample code segments will be given as an appendix.
The [incr Tcl] and [incr Tk] extensions fully address the issues of framework and mechanism for mega-widget production. They have established themselves as the defacto standard object-oriented extensions and have been chosen to provide the backbone for the [incr Widgets] set. Using these extensions, each mega-widget becomes a "class", defining a unique type of widget object in a separate namespace. This ensures that data and commands associated with an object are encapsulated, eliminating global name space pollution.
A primitive login screen is composed of two fields, each having a label and entry widget. The Tcl/Tk code required is shown in Figure 1. [incr Widgets] provides an Entryfield class which replaces this standard widget combination. This is shown in Figure 2. At this point, mega-widget usage is mostly a matter of convenience and minor savings in code, yet with a few additional requirements the benefits begin to escalate.
![]()
frame .login
pack .login -padx 10 -pady 10
frame .login.userFrame
label .login.userFrame.userLabel -text "User:"
entry .login.userFrame.userEntry
pack .login.userFrame -fill x -pady 5
pack .login.userFrame.userLabel -side left
pack .login.userFrame.userEntry -side left \
-expand yes -fill x
frame .login.passwdFrame
label .login.passwdFrame.passwdLabel \
-text "Password:"
entry .login.passwdFrame.passwdEntry
pack .login.passwdFrame -fill x -pady 5
pack .login.passwdFrame.passwdLabel -side left
pack .login.passwdFrame.passwdEntry -side left \
-expand yes -fill x
|
frame .login pack .login -padx 10 -pady 10 entryfield .login.user -labeltext "User:" pack .login.user -fill x -pady 5 entryfield .login.passwd -labeltext "Password:" pack .login.passwd -fill x -pady 5 |
Now let's add new requirements which might be required for a normal login screen. First, the labels should be left aligned. Next, the user field width should be limited to a maximum of 10 characters with input restricted to alphabetic characters and illegal character entry ringing the bell. As for the password, input must be masked and the return key should invoke a login procedure. We'll also present a more aesthetic interface by varying the textual background in the mega-widget. Since this last requirement applies to both entryfields, the option database will be used. Figure 3 illustrates the code needed to implement these new requirements using [incr Widgets]. Even without the presentation of comparative straight Tcl/Tk code, its safe to say that the benefits have increased.
![]()
option add *textBackground "GhostWhite"
frame .login
entryfield .login.user -labeltext "User:" \
-width 10 -fixed 10 -validate alphabetic \
-invalid bell
EntryField .login.passwd -labeltext "Password:" \
-show \267 -command LoginProc
Labeledwidget::alignlabels \
.login.user .login.passwd
pack .login -padx 10 -pady 10
pack .login.user -fill x -pady 5
pack .login.passwd -fill x -pady 5
|
This example gives just a sampling of the label control capabilities built into those classes based on the Labeledwidget class such as the Entryfield mega-widget. The label's position relative to its associated widget may be specified using standard directions: nw, n, ne, e, se, s, sw, and w. The label need not be limited to text, the class supports both bitmaps and images as well. A margin between the label and its associated widget may be given. Alignment is provided by adjusting the margins of a group of Labeledwidget based mega-widgets.
Currently, our login screen lacks a method of cancellation barring closure from the window manager decoration. Since this is not the most elegant method of window removal, "OK" and "Cancel" buttons seem like worthy additions. A well styled application would also make the buttons be of equal width and signify a default button associated with striking the return key through the appearance of an encompassing sunken ring. The Buttonbox class provides this functionality, making button management simple. As a manager widget, the Buttonbox controls the orientation, separation, and size of its button components. Buttons are added with the `add' command. The `default' command allows specification of a button within a sunken ring. Figure 4 presents the improved login screen.
![]()
option add *textBackground "GhostWhite"
frame .login
entryfield .login.user -labeltext "User:" \
-width 10 -fixed 10 \
-validate alphabetic -invalid bell \
-command {.login.bbox invoke}
entryfield .login.passwd -labeltext "Password:" \
-show \267 -command {.login.bbox invoke}
Labeledwidget::alignlabels .login.user .login.passwd
buttonbox .login.bbox -orient horizontal
.login.bbox add OK -text OK -command LoginProc
.login.bbox add Cancel -text Cancel -command exit
.login.bbox default OK
pack .login -padx 10 -pady 10
pack .login.user -fill x -pady 5
pack .login.passwd -fill x -pady 5
pack .login.bbox -fill x
|
Expanding further, a truly useful login screen should be a modal toplevel dialog widget. The [incr Widgets] Dialog class supports global, application, and non-modal dialogs (Application modal dialogs are implemented through the use of the BLT [5] extension). The difference being the degree of blocking. Global modal dialogs block all applications, whereas application modal dialogs only block the current application. This allows processing of the dialog contents following user response and dialog termination. Non-modal dialogs are non-blocking, enabling the application to continue. In this case, the actions attached to the buttons should perform all processing of the dialog contents.
The Dialog mega-widget class also contains a predefined extensible location called a "child site". This is an internally packed standard Tk frame which may be used as a parent for whole combinations of user specified widgets. Figure 5 illustrates the position of the child site frame in an instance of the Dialog class. In the login screen example, this frame can be filled with the user name and password Entryfield mega-widgets.
![]()
|
Once a dialog is created, it is displayed based on modality via the "activate" command. For application and global modal dialogs, control is not immediately returned. Instead, it is delayed until invocation of the "deactivate" command which accepts an optional argument that is returned as a result of the "activate" command. This allows user control of dialog unmapping, status notification, and determination.
For example, two buttons could be added to a global modal dialog, each button specifying a command which executes the "deactivate" command with a unique argument. The application could then activate the dialog, wait for deactivation, and perform actions based on the return value. This could all be placed in an "if" statement. The Dialog class uses this optional deactivation argument to provide default return values of zero and one for the "OK" and "Cancel" buttons as indicators of the dialog exit status. This ability proves useful for standard dialog management.
Figure 6 illustrates the new login screen implemented as an application modal Dialog composed of the two Entryfields. The need for explicit default button bindings has been left to the Dialog class, making the application even cleaner.The comparative amount of Tcl/Tk code required to provide the same flexible functionality would be quite substantial.
![]()
option add *textBackground "GhostWhite"
dialog .login -modality application -title "Login Screen"
.login hide Apply
.login hide Help
set cs [.login childSite]
entryfield $cs.user -labeltext "User:" \
-width 10 -fixed 10 -validate alphabetic \
entryfield $cs.passwd -labeltext "Password:" -show \267
pack $cs.user -fill x -pady 5
pack $cs.passwd -fill x -pady 5
Labeledwidget::alignlabels $cs.user $cs.passwd
if {[.login activate]} {
LoginProc [$cs.user get] [$cs.passwd get]
}
|
Since [incr Widgets] was designed to be a means rather than an end, each mega-widget is itself extensible. [incr Tk] provides the mechanism and framework to build new mega-widgets based upon existing ones using object-oriented techniques such as inheritance and composition. [incr Widgets] provides "child sites" which enable the visual aspects of a mega-widget to be augmented.
The login screen example could benefit from this capability. A new "Login" mega-widget derived from the Dialog class can be created, encapsulating the combination of widgets required to implement login screen functionality and enable reuse across many new projects. As a mega-widget, the Login class should maintain the standard options such as background and cursor. It should also provide unique options for specifying the labels of the entry widgets so they may be easily modified. Figure 7 shows the [incr Tcl]/[incr Tk] code needed to implement the "Login" mega-widget class.
The Login mega-widget can now be reused in new applications. It can be used as the front end to a database or a system administration tool. Since the labels were made public, the Login class can even be internationalized. For example, the "-userlabel", "-passwdlabel" options could be given in a foreign dialect or read from a language specific configuration file. Since the Login class was derived from the Dialog class, the button labels may be modified as well. To illustrate, Figure 8 depicts an instance of the Login mega-widget in Spanish.
itcl::class Login {
inherit iwidgets::Dialog
constructor {args} {
itk_component add user {
Entryfield $itk_interior.user \
-labeltext "User:"-width 10 \
-fixed 10 -validate alphabetic
} {
keep -cursor -background
}
pack $itk_component(user) -fill x -pady 5
itk_component add passwd {
Entryfield $itk_interior.passwd \
-labeltext "Password:" -show \267
} {
keep -cursor -background
}
pack $itk_component(passwd) -fill x -pady 5
hide Help
hide Apply
eval itk_intialize $args
}
itk_option define -userlabel userLabel Text "User:" {
$itk_component(user) configure \
-labeltext $itk_option(-userlabel)
Labeledwidget::alignlabels $itk_component(user) \
$itk_component(passwd)
}
itk_option define -passwdlabel passwdLabel Text "Password:" {
$itk_component(passwd) configure \
-labeltext $itk_option(-passwdlabel)
LabeledWidget::alignLabels $itk_component(user) \
$itk_component(passwd)
}
method name {} {
return [$itk_component(user) get]
}
method passwd {} {
return [$itk_component(passwd) get]
}
}
Login .login -title "Login Screen" -modality application
if {[.login activate]} {
LoginProc [.login name] [.login passwd]
}
|
|
One final point. It should be noted that the lack of an option being made public does not make it inaccessible. The dilemma is that keeping all options tends to cause option explosion, yet only providing a few limits usefulness. As a general rule, standard options should be kept as well as frequently used options. In the Login mega-widget, standard options were kept and each label was provided a unique option due to a high degree of anticipated usage. Other options such as "-foreground" can be accessed on an as needed basis via the [incr Tk] `component' command or using the option database. Figure 9 illustrates both of these methods of component access.
option add *Login*user.foreground Red .login component user configure -foreground Red |
As applications increase in size, invariably requiring a main window and numerous dialogs, mega-widget usage offers significant productivity gains and increased reliability. This could also be seen in the example as well. A savings of a sizable amount of straight Tcl/Tk code was achieved and implementation of such things as modality was abstracted into the Dialog mega-widget and it's base classes. Since the Dialog class is encapsulated and tested, the Login mega-widget was built on a sound foundation. Errors typical of "cut and paste" built applications, such as forgetting to release a grab, have been eliminated. Developers are free to concentrate on the application and not low level problems.
To draw an analogy to current building construction techniques, Tk widgets are bricks and mega-widgets are pre-formed walls built with bricks. It is much quicker to construct a large building using walls than bricks. Although in the construction industry, this creates a lot of cookie cutter, identical, and boring buildings, application users appreciate this consistency, especially when it increases usability. A user shouldn't be confused during the operation of an application by being presented variant combinations of the same widget patterns. Each one having a unique behavior which users must learn during operation, rather than from prior experiences with other more standard interfaces.
The significance of a consistent style should not be overlooked. It doesn't always appear in typical Tcl/Tk applications. This stems from Tk itself. Its greatest asset is also a liability: a simple and easy to use widget set. Tk can make it easy for novice programmers to construct interfaces which conform to random personal styles rather than any known industry standards. Many unusual applications have been produced with Tk which have sunken buttons, raised entries, or are packed with such a lack of padding as to create "brick walls" of widgets. Applications which exhibit these qualities can be found at the Tcl/Tk archive site. Mega-widgets can lessen the occurrence of these visual works of art while maintaining simplicity and ease of use. For example, use of the [incr Widgets] Buttonbox mega-widget can stop the button "brick wall" effect.
The Motif look-and-feel was chosen because of its strength in the industry and customer requirements. The demand of the current [incr Widgets] customer base is a Motif appearance and behavior, regardless of the underlying implementation. Thus, very few liberties were taken in the visual style and behavioral aspects of [incr Widgets]. Instead, concepts such as extensible child sites and flexible component configuration option sets have been implemented which allow developer divergence from the Motif style on an as needed basis.
Consider an application which requires a icon selection dialog, visually displaying the icon as the textual name is selected from the list. Also, suppose we would like to see this canvas on which the icon is presented lie between the listbox and entry widget. This could easily be implemented using the [incr Widgets] Selectiondialog mega-widget which maintains a child site, as depicted in Figure 10.
|
selectiondialog .iconSel -title "Icon Selector" \
-itemslabel Icons -selectionlabel Icon \
-childsitepos center -itemscommand SelectProc
.iconSel hide Help
.iconSel hide Apply
set cs [.iconSel childsite]
canvas $cs.canvas -height 70 -relief raised -borderwidth 2
pack $cs.canvas -fill x -expand yes
proc SelectProc {} {
.iconSel selectitem
set c [.iconSel childsite].canvas
$c delete all
$c create bitmap [expr [winfo width $c] / 2] \
[expr [winfo height $c] / 2] \
-bitmap @~/xbm/[.iconSel get].xbm
}
.iconSel insert items end bomb compress core dsc emacs \
keyboard telephone trash workstation
.iconSel activate
|
The advantages of child sites can be seen by examining the opposite situation. Had the Selectiondialog been designed minus a child site, the user would have been forced to create the icon selector from scratch or become aware of its internal packing and attempt to repack around the canvas. A take-it-or-leave-it design such as this would be limiting, sacrificing possibilities of reuse.
The means by which a child site may be filled is not a limiting factor in the [incr Widgets] set. Either composition or inheritance may be used. In the login screen example, both of these mechanisms were demonstrated. First composition was used. Later, as the Login mega-widget class was produced, the same child site was filled by means of [incr Tcl]'s inheritance feature. The implementation of child sites and the means by which they may be accessed in [incr Widgets] deserves closer inspection.
[incr Tk] has several base classes from which the [incr Widgets] class hierarchy is derived. As base classes they provide option management, standard methods, and a parent for components called the "hull" widget. The path to this widget is contained in a protected class variable named "itk_interior". Many mega-widgets within [incr Widgets] successively maintain this variable in the hierarchy. As a mega-widget is constructed, new components are built off the path stored in the "itk_interior" variable. The mega-widget may also construct a new hull and store its path in "itk_interior" for a future derived class to use. A `childsite' method is provided for composition support.
This is a very useful feature. For example, all the mega-widgets which support scrollbar attachment do so at the developer's discretion. One may choose to have each scrollbar independently displayed either statically, dynamically, or never. A dynamic scrollbar would appear as needed based on the number of elements in the widget and their ability to fit in the allotted space, whereas a static one is always displayed. Thus, scrollbars have built-in intelligence.
Similarly, Buttonbox usage is not limited to horizontal button display management. Instead, buttons may be oriented vertically as well as horizontally. Also, each button may be referred to by its associated tag in commands which allow them to be hidden, shown, configured, or made the default.
Flexibility is built into the larger scale mega-widgets as well. The Selectionbox class allows specification of labels, their position relative to their associated widget, and control over the display of the each element. The Fileselectionbox provides this same ability. Thus, the filter or selection labeled entries can be unmanaged as well as the file and directory lists.
Large scale flexibility presents significant advantages. Applications may be designed in a more interactive manner. Consider the icon selector dialog example again. Suppose an alternate presentation of the dialog was to be considered. One in which the icon canvas appears above the list, the selection entry widget is removed, and an apply button is added. This could be quickly examined by configuring the components as given in Figure 11.
|
.iconSel configure -childsitepos n -selectionon no .iconSel show Apply |
The ability to reconfigure components also allows programs to be built which change appearance on the fly. An application which demands multiple flavors of a mega-widget with different looks can create one instance and change the options between uses. This can be much more efficient, since construction time is much more costly than the time required to configure and map the widget.
For example, consider an application which must confirm a user request prior to performing the operation. In addition, due to the serious nature of the operation the user must confirm positively twice. The following code segment creates the initial message dialog and configures the message to ask "Are you sure ?". The dialog is then mapped with the "activate" command. If the user responds positively, then the message is changed to "Are you really sure ?" and redisplayed. Only with two affirmative replies does the script perform the operation. Figure 12 depicts the dialog presentations with different messages and the associated code.
|
This same instance of the message dialog can be reconfigured into a error dialog. All the options can be dynamically changed. It is possible to not only change the bitmap but its location as well. Furthermore, we can modify the text of the buttons and make the dialog non-modal. We'll also change the orientation and position of the buttons to be vertical along the right hand side. Figure 13 shows the final product. It is important to note, that no new message dialog has been created, instead the existing one has been reconfigured.
![]()
.md configure -bitmap error -imagepos n \ -text "Unable to access device" \ -modality none -buttonboxpos e .md buttonconfigure OK -text "Retry" .md buttonconfigure Cancel -text "Cancel" .md activate |
Inheritance proved to be a valuable tool during [incr Widgets] development. The impact of changes due to Tk 4.0 were significantly lessened. For example, as image support was added to Tk, a single option was added to the LabeledWidget class which was then inherited by derived classes in the hierarchy. Also, bugs fixed in base classes applied to all derived ones. This made for quick and easy maintenance. On a similar note, errors introduced in lower level classes had broader effects. Fortunately, this was rare and easily detected due to the magnified repercussions.
Maximum reconfigurability comes at the price of quickly multiplying options in an inheritance hierarchy. In an effort to avoid the usability problems associated with Motif's bulky resource set, [incr Widgets] imposed an 80/20 rule. If 80% of the user community could be viewed as having no interest in an option, it was excluded. Users could always use the built-in [incr Tk] `component' command to configure an option.
The incorporation of a regression test suit was a definite plus. The [incr Widgets] test suite is a blatant rip-off of the work done by Ousterhout and May-Pumphrey for Tcl/Tk [6]. The test suite consistently exposed flaws which hand testing left hidden. Especially those bugs dealing with large scale component configuration. The test suite also doubles as a good visual demo.
Absolutely no reuse of any kind occurs until a widget set becomes well documented. This includes man pages, user's guides, and demos. Unless documented, reuse is a localized event at best. There is no such thing as self-documenting code. Instead, the demand is for self-documenting engineers.
Public contributions to the [incr Widgets] mega-widget set are welcome and encouraged. Those mega-widgets which currently compose [incr Widgets] should be used as a model. Contributed mega-widgets should meet or exceed the objectives set forth in this paper such as extensible child sites, flexible component configurations, and style consistency. The coding and comment style must also be maintained. Man pages, demos, and test scripts are mandatory.
In short, [incr Widgets] is a library of reusable mega-widgets that can be easily extended, allowing quicker development of large scale applications. It has been successfully used in several projects, including mission-critical telecommunication applications delivered to Japan, Great Britain, and Australia. As development continues, existing classes are being extended and new classes are being added. Development time has been drastically reduced. New dialogs can be created in hours. Whole applications in days. Reuse is a reality. New projects are benefitting from the work of others. [incr Widgets] is an [incr Tk] success story.
[incr Widgets] Tour