                             Introduction
                             ------------

	This package is the first release of Tix: Tk Ioi's eXtension.
Tix is intended to supplmement the standard Tk widget set. Rather than
being built from scratch, the Tix widgets are implemented in TCL by
using the existing widgets as building blocks.

	Although many extensions to Tk exist today, Tix stands unique
because it sticks to the standard Tk programming interface. All the
widgets are used the same way as the standard Tk widgets. For example,
if you want to use a TixScrolledListBox, you'd say:

	tixScrolledListBox .sbox

Just as in Tk, after the widget's creation, it is accessed by the
widget command. For example, to configure the widget:

	.sbox config -geom 10x10

Note that the configuration opations can be supplied as arguments to
the widget creation command as well. So the above two calls can be
combined into one:

	tixScrolledListBox .sbox -geom 10x10

The Tix widgets also have their own widget commands. For example, you
can insert an item into the scrolled list by saying:

	.sbox insertlist "Hello there!"

You can also pack or place the Tix widgets using one of the geometry
managers:

	pack append . .sbox {expand fill}


o Release note:

	I tried to write Tix exclusively in TCL. Unfortunately, to use
the full capability of the current release, you need a patch to your
wish shell. Without the patch, Tix can still run but then you will not
be able to use the TixComboBox widget. Please refer to the file
Readme.patch for further details.

	For a more detailed documentation of the Tix widgets, please
read the file Readme.widgets.



			Compound widgets
			----------------

	The main purpose of Tix is to construct _compound widgets_ by
using the existing Tk widgets as buliding blocks. This section
explains the needs for compound widgets and the advantages of their
implementation in TCL.

	First of all, compound widgets can be used by the application
programmers as a convenience for creating the commonly needed
constructs. One example for such a construct is the scrolled listbox
To build a scrolled listbox, an application programmer needs to
create several Tk widgets and then pack them together. This becomes a
nuisance especially when the same consturct is needed many times in an
application. By using the TixScrolledListBox widget, only one widget
needs to be created.

	Second, by using the compound widgets, the user interface
specification can be made more structural. Some Tk/Tcl applications
have notouriously unreadable code. They specify the interface using
only the primitive Tk widgets and the higher level constructs of the
interface are lost in a sea of unnecessary details. With the help of
the compound widgets, the structure of the interface becomes more
obvious and the readability of the code can be greatly improved.

	Third, the programming techniques illustrated by Tix can be
used to rapidly develop new widgets. For example, the combo box widget
(excluding documentation) was written in about five hours. The speed
and ease with Tix can be astonishing to the widget programmers who are
used to programming in C/Xlib. The reason is that, compared to C, TCL
is much easier to write and debug. Also, TCL relieves the programmer
from the many details that they must consider in C. Finally, Tk
provides many high level tools that are unparalleled by the primitive
Xlib functions.


                  The design and implementation of Tix
                  ------------------------------------

The design
----------

	To describe the design of Tix, I first have to emphasis that
Tix is not a replacement, but an extension to Tk. Since Tix is an
extension to an existing software, its design is constrained by many
extra factors.

	First, an extension must conform to the design of the existing
software. This means that the programming interface used by Tk in
widget creation and configuration must not be altered. Also, Tk's
convention of using widget commands must be observed. For example, if
an extension provides a new type of widget, say Foobar, it must be
used in the following way:

	Foobar .foobar -geom 100x10 -barcolor red
	pack append . .foobar left
	.foobar invoke
	.foobar config -state disabled
	
In contrast, some early Tk extension packages inappropriately use the
"functional approach".  Their widgets are created and manipulated by a
set of functions. The above example will appear as:

	CreateFooBar .foobar 100 10 red
	InvokeFooBar .foobar
	DisableFooBar .foobar

If an extension package does not observe the conformation rule and
introduces a new programming style when it is not absolutely necessary,
it will be doomed to failure --- the new approach is foreign to the
users of the existing software and it will be difficult to gain
wide acceptance from them.

	Second, the extension packages must be ready to co-esist and
co-operate with other extensions. If different packages introduce
different programming interfaces, it will be increasingly difficult for
the users to use multiple extension packages. If one package decides to
configure their widgets in the order

	ConfigFoobar {widget x y width height color state}

and another uses the format

	ConfigFoobarWidth   {widget width }
	ConfigFoobarHeight  {widget height}
	ConfigFoobarColor   {widget color }

the result is that the users will be confused by the different
conventions in different packages and will be reluctant to use them.

	This is a serious problem in the Tk community because of the
small sizes of the extension packages. If the packages were large, it
would still make sense to learn their varied programming interface.
However, many Tk widget contributers only write a couple of widgets
and contribute them to the community. We have to make sure it is easy
to integrate a large number of small packages so that the efforts of
the widget contributors can be worthwhile. Hence, the solution can be
reached only if all the extension packages conform to the Tk
programming interface.


The Implementation
------------------

	Tk is an object system, where many instances of objects exist
and cooperate with each other. In a well designed object system,
firstly, the objects must be relatively independent of each other,
that is, the behavior of an object must not be affected by the others
if not necessary. Secondly, there must be good communication channels
between the objects, that is, when it is necessary, the widgets can
influence the behavior of each other in the most efficient and precise
way. To achieve the first goal, Tk maintains private data for each
individual widget. For the second, Tk uses widget commands for the
widgets to commuincate with each other, mainly by widget commands. The
Tk implementation is written in C and will be illustrated in the
fourth part of the Tk book. In this paper, I will explain how Tix
achieves these goal in its TCL implementation.

	In an object oriented programming system, there is the notion
of object classes. An object class defines a data structure and a set
of related member functions (or methods) to operate on the data
structure. The association between the member functions and the data
structure must be speficied implicitly or explicitely.

	Private data
	------------
	In the case of the combo-box, there is a configuration option
-height which defines the height of the pop-up listbox. Every time the
listbox is popped up, we need to access this information to set the
listbox to the desired size. We can have a global variable
combo_box_height to store this information, but then we will lose the
flexibility of having different configuration for different
combo-boxes and infringe the rule of object independence. Tix chooses
to keep the information for each combo-box in its own private data
structure: An associative array is created for each combo-box. The
array has the same name as the combo-box. For example, a combo-box
names .cbox owns an array .cbox(). The height of the combo-box is
stored in .cbox(height).

	In order to associate the member functions to the combo-box
data, the name of the combo-box is passed to all the member functions.
For example, when the combo-box .cbox needs to pop up the listbox, it will
call the member function Combo_PopupListBox and passes to it the name
.cbox. The member function will then refer to the array .cbox(), reads
the information .cbox(height) and displays the listbox correctly.

	The implementation of the above is a little tricky because it
is not sytactically supported in TCL. It can be explained by the
following fragment of code:

	Combox_SetHeight {var height} {
		upvar #0 $var data
		set data(height) $height
	}

If we have a combo-box .cbox, we will configure its height by calling

	.cbox configure -height 200

This call will be redirected by the widget command to

	Combox_SetHeight .cbox 200

The first line in Combox_SetHeight,

	upvar #0 $var data

is equivalent to "upvar #0 .cbox data" and it will make data() an
alias to the global array .cbox(). Then the second line "set
data(height) $height" will set the array member .cbox(height) to 200

	The use of "var" and "data" is tricky and not very
aesthetically pleasing. I hope future release of TCL will have direct
support of this construct so that the code can be written in a more
readable and intuitive form.

	Other information can be stored in the array. The most
commonly used member is data(root). It stores the name of the root
widget (normally a frame) of the compound widget.


	Widget Commands
	---------------

	Each time a combo-box is created, a widget command is
automatically created for it. The combo-box .cbox will have a widget
command .cbox, which is created by the function Combox_CreateWidgetCmd.

	proc Combox_CreateWidgetCmd {var} {
		upvar #0 $var data
		set w $data(root)

		proc $w {option args} {
			set var [lindex [info level 0] 0]
			upvar #0 $var data

			...
		}
	}


Again, when we create the combo-box, we issue the command:

	tixComboBox .cbox

tixComboBox will in turn call:

	Combox_CreateWidgetCmd .cbox

Combox_CreateWidgetCmd will get the name of the widget invoke the proc
command with:

	proc .cbox {option args}

Now a command .cbox is created for us. Each when we issue a widget
command of .cbox, actually we execute the line starting with:

	proc $w {option args} {
		...
	}

The procedure has to know which combo-box it has to operate on. It
calls 

	set var [lindex [info level 0] 0]

to get the name of the procedure. If we call

	.cbox config -height 200

var will be set to .cbox and then we can proceed to the normally
"upvar #0 $var data" sequence.


	Renaming the widget command of the root widget
	----------------------------------------------

	Every compound widget is built by combining several primitive
widget. For example, the visible part of the combo-box consists of an
entry and a button. These primitive widgets are normally packed in a
frame, which is called the root of a compound widget. When you pack
the combo-box with other widgets, you are actually packing its root
widget -- the outmost frame.

	In the above example, The window name .cbox actually is the
name of the root widget. The root widget originally will have the
widget command .cbox. Since we also want to use the command .cbox to
access the combo-box, the original command .cbox is renamed to
.cbox.root. The new .cbox command receive all the commands from the
user. If it recognizes the parameters, it will act on them. If it
doesn't, it will pass the parameters to .cbox.root. For example, a
call to

	.cbox addhistroy "hello"

will invoke the new .cbox command but a call to

	.cbox config -border 10

will be redirected to .cbox.root


	Private data protection
	-----------------------

	Private data protection is a crucial part of object-oriented
design but it is not supported by TCL. After reading the source code
of Tix, it might be tempting to access the internal data of the Tix
widgets directly. For example, any part of the program can read or
change the variable .cbox(height) to achieve the same effect of
calling ".cbox config -height". However, such pratices are dangerous
because they might affect the behavior of the Tix widgets in
unexpected ways. Also, the private data structure might be chaged in
the future and therefore render the nasty code incompatible with
future releases. The same applies to accessing the internal widget
members of a compound widget. Some of the internal widgets can be
obtained leagally. For example, for the combo-box .cbox, the call

	.cbox getlistbox

will return the path name of the listbox used inside the combo-box. In
most cases, other internal widgets are hidden from the outside world
should never be accessed directly.
	

			Conclusion
			----------

	Since the Tix widgets stick to the standard Tk programming
interface, they can be integrated seamlessly into the Tk widgets. As
the development of Tix goes on, more types of widgets will be developed
and they will prove to be valuable tools for the Tk application
programmers.

	Nevertheless, the current release of Tix is the only first
release of the package. Many new features will be introduced in future
releases. One such feature will be the ability of configuring the Tix
widgets from the option database.

	In this release, my primary intention is to introduce the new
programming techniques developed in Tix to the Tk community. Although
there might be practical use the the widgets in the current package, I
have to stress that this release was conceptualized and implemented in
about two weeks. Since I have not yet the time to rethink about the
different aspects of Tix, there will surely be insufficiency and
errors in the current design. At this stage, I will not recomment
using the Tix widgets in critical application programs. However, I
encourage the Tix users to test out and, most of all, improve the
ideas presented in this paper. If you encounter any bugs in Tix,
please report them to ioi@graphics.cis.upenn.edu. Any comments or
criticisms will indeed be appricated.

