Skip to main content

Gnocl Tutorial #1 -The Basics

The whole idea behind developing the Gnocl Tcl package is 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 understandin 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 persmissions of the file to get the schell 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 successully 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, save and re-run.

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 straightforward to understand. Widget options are set in a way familiar to anyone with exposure to using console based applications. 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:

# 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? A toplevel window has only one child, the choice of its child is important. In order to add more widget What we need to first add a container -- a gnocl::box. The next script illustrates this point.

# 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 take more than one value, we sent a list of values which, in this case are strings containing the names of the buttons previously created. A third button, but3 is created later which then added to the list of children.

So far, we have made some pretty large buttons. Resizing the window will, of course, resize the child widgets it contains; in gnocl-ese 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,

# 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 remains 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. Clearly, the script is controlling what proportion of the window display space will be occupied by a widget. This is achieved 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 the way is a boolean, that means either a yes (1) or no (0) option.


Reblog this post [with Zemanta]

Comments

Popular posts from this blog

gnocl::calendar

Given this module some attention today. Added some of the more package wide options to the module and created customised handler for setting the month. (For some odd reason months are are counted 0-11 whereas days are 1-31.) There's still a little more to do to this one including the addition of code to store diary details. Here's the working test script to show the range of options at work. The percentage substitution string item %e explores something that I've been toying with, the name of the signal/event that initiated the call. Ok, a script can keep its own internal trace but who knows, it might prove useful. #--------------- # calendarTest.tcl #--------------- # Author:   William J Giddings # Date:     07/05/09 #--------------- #!/bin/sh # the next line restarts using tclsh \ exec tclsh "$0" "$@" #--------------- package require Gnocl set cal [gnocl::calendar] $cal configure -day 8 -month 7 -year 1956 $cal configure -rowHeight 1 -colWidth 1 $ca

Simple Runtime Debugging Message Dialog

At times it's useful to see what values variables hold, or offer some pause point before the code goes elsewhere before causing havoc. Its possible to write output to the terminal but this can get lost in copious forms of other outputs, besides, there's no pausing the script execution either. The following proc creates a custom dialog which displays ad message along with the point in the calling script from which it was invoked. ## simple runtime debugging feedback dialog, alternative to console based gnocl::msg # @param msg message to display # @returns none # proc xxx::msg {txt} { set frame [info frame -1] append msg "Message:\n\n" append msg " $txt \n\n\n" append msg "Called from:\n\n" append msg "Proc:\t[lindex [info level -1] 0]\n" append msg "File:\t[file tail [dict get $frame file]]\n" append msg "Line:\t[dict get $frame line]\n" gnocl::dialog \ -type info \ -text $msg

Creating a button box with right aligned widgets

The dialog widget has its own internal functionaluty to create and position buttons at the bottom right corner of the window container. When creating these for ourselves it must be born in mind that default settings for fill and expand are both 0.5. Failing to set these will always place the child objects in the centre, regardless of alignment. For most cases these defaults are acceptable but, to create that dialog-button arrangement, use the following snippet as a model!   # to right align completely, set expand and fill to 0 set hbox [gnocl::hBox] set b1 [gnocl::button -text Select \                -data $lst                 -onClicked { puts DO-SOMETHING-WITH-%d} ] set b2 [gnocl::button -text Cancel -onClicked { puts DONE! } ] $vbox add $hbox -expand 0 -fill 0 -align right $hbox add $b1 $hbox add $b2