The whole idea behind creating the Gnocl package for Tcl was to make to process of developing
Gtk+/Compliant applications easy to develop. Ordinarily, creating a
gtk+ application requires not only a good understanding of the C
programming language and its build tools, but also practical
familiarity with the innards of the various Gtk+ libaries.
The tcl scipting
language was designed to isolate (or spare) the scripter from the
daunting task of negotiating the vast array of build libraries and
needed to get event the most simplest of task-driven applications to
work, gnocl does the same. Unlike other bindings such as PyGtk which
places a 'wrapper' around Gtk libraries making them accesible to the
script, such an approach still requires the scripter to understand
the innards of the Gtk libraries. For the newcomer, the big-jump into
developing useful code is less than programming directly in C, but
still a lengthy task when compare to the directness of the Gnocl
approach.
So, how does Gnocl
work? The idea is to maintain the tool-command paradigm that forms
the heart of Tcl and it companion package, Tk. Here a glimpse at a
first application would be useful. As were running under some form of
*nix, we need to open a script file and enter the following lines.
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"
package require Gnocl
Save this as script1.tcl
At the command prompt, change the permissions of the file to get the shell to run the script as an executable. To do this, simply run:
chmod +x *.tcl
Then run, using
./script1.tcl
Assuming, that we've
already successfully installed Tcl and the gnocl packages, this will
produce absolutely nothing on screen! In fact, this is good. It tells
that all the packages are properly installed. Now add the following
line of code;
gnocl::window
Voila! The window is now open. This one line of script provides the scripter with a whole raft of pre-porgrammed options. Ranging from event handling, style settings and even compositing to screen with a bitmask. This, is he beauty of the Tcl approach. Lets now create a button. We can add the following line, just above the gnocl::window command.
set but1 [gnocl::button
\
-text "Hello World!" \
-onClicked {puts "Hello World"}
]
This simple command
look straghtforward to unserstand. Widget options are set in a way
familiar to anyone with exposure to using console base application.
The global variable 'but1' needs to be set, so that the script can
directly handle the new widget. To tell the system to add the button
as the 'child' of the window 'parent', modify the gnocl::window line
to read:
gnocl::window -child
$but1
But, just for fun, also add the following extra options to set the title of the window, change its size and what to do when the close button is clicked.
gnocl::window \
-child $but1 \
-title "My First Gnocl App" \
-onDestroy {exit} \
-widthRequest 320 \
-heightRequest 200
Here's the full listing:
Script 1
# script1.tcl #!/bin/sh # the next line restarts using tclsh \ exec tclsh "$0" "$@" package require Gnocl set but1 [gnocl::button \ -text "Hello World!" \ -onClicked {puts "Hello World"} ] gnocl::window \ -child $but1 \ -title "My First Gnocl App" \ -onDestroy {exit} \ -widthRequest 320 \ -heightRequest 200 As can be seen, a
single line of script can be quite long and dificult to read. Unlike
other scripting languages which are quite 'fixed' in their
formatting, Tcl is flexible. To break commands over multiple lines
simple add '\'. This will tell the Tcl interpreter that that next line is still a
part of the current command.
This is about the
simplest application that can be made. But, what if we want to add
more widgets? in short, a toplvel window has only one child, the
choice of its child is important. In order to add more widget What we
need to add first is a container -- a gnocl:box. The next script
illustrates this point.
Script 2
#script2.tcl#!/bin/sh # the next line restarts using tclsh \exec tclsh "$0" "$@" package require Gnocl set but1 [gnocl::button \ -text "Hello World!" \ -onClicked {puts "Hello World"} ] set but2 [gnocl::button \ -text "Good Morning!" \ -onClicked {puts "Good Morning"} ] set box [gnocl::box -children "$but1 $but2" ] set but3 [gnocl::button \ -text "Good Afternoon!" \ -onClicked {puts "Good Afternoon"} ] $box add $but3 gnocl::window \ -child $box \ -title "My First Gnocl App" \ -onDestroy {exit} \ -widthRequest 320 \ -heightRequest 200 Here we can see that but2 was created and added directly to the box at initialisation. As the -children option can only take one value, we sent a list of
values which, in this case are strings containing the names of the
buttons just created. A third button, but3 is created later which can
also be added. Here, we see another great feature of the the Tcl
paradigm, the command. Here, 'add' simple instructs the box widget to
act as the 'parent' of this new item. But, of course, each child can
only have one parent!
So far, we have made
some pretty large buttons. Resizing the window will, of course,
resize the child widgets it contains; in gnocl-ish the widgets are
'filling' their parent, and 'expanding' as the toplevel window that
contains them all is resized. As might be expected, both 'fill' and
'expand' are switchable options. To best demonstrate this feature,
lets work with an alternative version of script2.tcl,
Script 3
# script3.tcl#!/bin/sH# the next line
restarts using tclsh \exec tclsh "$0"
"$@"
package require Gnocl
set but1 [gnocl::button \
-text "Hello
World!" \
-onClicked {puts
"Hello World"} ]
set but2 [gnocl::button
\
-text "Good
Morning!" \
-onClicked {puts
"Good Morning"} ]
set but3 [gnocl::button
\
-text "Good
Afternoon!" \
-onClicked {puts
"Good Afternoon"} ]
set box [gnocl::box ]
$box add $but1 -fill {0
0} -expand 0
$box add $but2 -fill {1
1} -expand 1
$box add $but3 -fill {0
0.5} -expand 1
gnocl::window \
-child $box \
-title "My
First Gnocl App" \
-onDestroy {exit} \
-widthRequest 320 \
-heightRequest 200
Running this script and
resizing the window will show some interesting behaviours; but1
always remainds the same size, but2 will expand to fill whatever
space is available, whereas but3 does not change its width but only
its height to fill half (i.e 0.5) of its available space. As can be
seen, the script can control just what proportion of the window
display space will be occupied by a widget by providing a 'fill
factor' between 1 and zero. In most instances, however, these will
typically be either 0 or 1. The -expand switch, by thge way is a
boolean, that means either a yes (1) or no (0) option.